使用SpringBoot的@Async实现异步调用方法,以及自己开启新线程异步调用

使用SpringBoot的@Async实现异步调用方法,以及自己开启新线程异步调用一.springboot的@Async注解实现异步要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了1.准备工作准备一个springboot工程,在Application类上加上EnableAsync注解开启异步/***@Author:zgd*@Date:18/09/1210:27*@Description:…

大家好,又见面了,我是你们的朋友全栈君。

Page Counter

一. springboot的@Async注解实现异步

要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了

1.准备工作

准备一个springboot工程,在Application类上加上EnableAsync注解开启异步

/** * @Author: zgd * @Date: 18/09/12 10:27 * @Description: */
@SpringBootApplication
@EnableAsync
public class Application { 
   

  public static void main(String[] args) { 
   
    SpringApplication.run(Application.class,args);
  }

}

这个注解如果不加,@Async注解失效

2.controller

写一个同步接口和异步接口

package com.zgd.demo.thread.asyn.controller;

import com.zgd.demo.thread.asyn.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;

/** * @Author: zgd * @Date: 18/09/12 10:26 * @Description: hello */
@RestController
@RequestMapping("/hello")
public class HelloController { 
   

  @Autowired
  private HelloService helloService;

  /** * 异步方法 * @return */
  @RequestMapping("/asyn")
  public String getAsynHello(){ 
   
    long n = Instant.now().toEpochMilli();
    //异步
    String s = helloService.asynchSayHello();

    long f = Instant.now().toEpochMilli();
    return s + " 时间: " + (f-n);

  }

  /** * 同步方法 * * @return */
  @RequestMapping("/sync")
  public String getSyncHello(){ 
   

    long n = Instant.now().toEpochMilli();
    //异步
    String s = helloService.synchSayHello();

    long f = Instant.now().toEpochMilli();
    return s + " 时间: " + (f-n);
  }
}

3.helloService

写一个HelloService接口,并实现该接口

package com.zgd.demo.thread.asyn.service.impl;

import com.zgd.demo.thread.asyn.service.HelloService;
import com.zgd.demo.thread.asyn.service.SleepService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/** * @Author: zgd * @Date: 18/09/12 10:43 * @Description: */
@Service
public class HelloServiceImpl implements HelloService { 
   

  @Autowired
  private SleepService sleepService;

  @Override
  public String synchSayHello() { 
   
    try { 
   
      sleepService.syncSleep();
      return "hello world,这是同步方法";
    } catch (InterruptedException e) { 
   
      e.printStackTrace();
      return "error";
    }
  }

  @Override
  public String asynchSayHello() { 
   
    try { 
   
      System.out.println("主线程 "+Thread.currentThread().getName());
      sleepService.asyncSleep();
      return "hello world,这是异步方法";
    } catch (InterruptedException e) { 
   
      e.printStackTrace();
      return "error";
    }
  }
}

这里为了模拟应用场景,将耗时的方法放在另一个service里面,就叫SleepService,同样的,实现这个接口

package com.zgd.demo.thread.asyn.service.impl;

import com.zgd.demo.thread.asyn.service.SleepService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/** * @Author: zgd * @Date: 18/09/12 10:46 * @Description: */
@Service
public class SleepServiceImpl implements SleepService { 
   

  @Override
  public void syncSleep() throws InterruptedException { 
   
    System.out.println("线程名: " +Thread.currentThread().getName());
    System.out.println("开始同步休眠3秒");
    Thread.sleep(3000);
    System.out.println("同步休眠结束");
  }

  @Override
  @Async
  public void asyncSleep() throws InterruptedException { 
   
    System.out.println("次线程 "+Thread.currentThread().getName());

    System.out.println("开始异步休眠3秒");
    Thread.sleep(3000);
    System.out.println("异步休眠休眠结束");
  }
}

两个方法都是休眠3秒,aysncSleep方法上面有一个@Async注解

4.测试

  • 同步
    访问 http://localhost:8080/hello/sync
    在这里插入图片描述
    控制台
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpLDV4Mc-1587893525642)(https://i.imgur.com/aICMDZA.png)]
    要3秒的时间才能收到响应

  • 异步
    访问 http://localhost:8080/hello/asyn
    在这里插入图片描述
    在这里插入图片描述
    可见主线程和次线程打印出来的线程名不一样,也就是springboot帮我们开启了一个线程去处理

注意事项

  1. 必须要加@EnableAsync注解
  2. 不能在同一类下调用@Async注解的方法,比如A类下有a和b方法,b方法有@Async注解,不能直接这样a调用b,要把b放到其他类中
  3. @Async也可以打在类上,这样类下面的所有方法都是异步的(被其他类调用的时候)

二.开启线程实现异步

如果我们没有使用springboot,使用传统的方法怎么异步调用方法?还是开启一个新的线程

1.controller

增加一个接口

/** * 同步方法 * * @return */
  @RequestMapping("/thread/asyn")
  public String getThreadSyncHello(){ 
   
    long n = Instant.now().toEpochMilli();
    //异步
    String s = helloService.threadAsynchSayHello();
    long f = Instant.now().toEpochMilli();
    return s + " 时间: " + (f-n);
  }

2.service

HelloServiceImpl

@Override
  public String threadAsynchSayHello() { 
   
    //还是休眠3秒
    Runnable runnable = ()-> { 
   
      try { 
   
        sleepService.syncSleep();
      } catch (InterruptedException e) { 
   
        e.printStackTrace();
      }
    };
    System.out.println(Thread.currentThread().getName()+" 开启新线程");
    new Thread(runnable).start();
    return "hello world,这是开启线程的异步方法";
  }

3.测试

我们访问 http://localhost:8080/hello/thread/asyn
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqsAimN4-1587893525654)(https://i.imgur.com/huTAJAm.png)]

在这里插入图片描述

同样的两个线程名不一样,开启了一个新线程处理,并且多次测试可以看出,自己直接开启线程比@Async要快几毫秒,不过可以忽略不计了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/157522.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 第 3.2 节 SQL

    第 3.2 节 SQL

    2021年3月12日
    132
  • 怎样做一个软件项目经理助理_软件开发项目经理的职责

    怎样做一个软件项目经理助理_软件开发项目经理的职责第一部分:软件项目经理的要求首先是一个管理者。其次熟悉某些工具,某几种语言。行业背景。项目管理技能。软件项目经理面临的恶劣环境,我们绝大部分软件企业执行在相对混乱的状态(CMM一级),组织不大可能

    2022年8月3日
    7
  • Latex——在线快速生成表格代码

    Latex——在线快速生成表格代码latex在线生成表格的网站:http://www.tablesgenerator.com/latex_tables这个网站可以通过三种方式来生成latex表格代码:1、自己设置表格;2、直接导入csv表格;3、直接复制表格内容1、自己设置表格点击File,选择newtables,可以设置需要的行列数2、点击importcsvfile,可以直接导入3、点击paste…

    2022年8月11日
    6
  • web navigator_前端如何传参数为一个对象

    web navigator_前端如何传参数为一个对象Navigator对象一、Navigator对象简介二、Navigator对象集合三、Navigator对象属性1.appCodeName、appName、appVersion(1)属性介绍(2)具体演示2.cookieEnabled、onLine(1)属性介绍(2)具体演示3.platform、userAgent(1)属性介绍(2)具体演示四、Navigator对象方法1.javaEnabled()五、Navigator对象描述一、Navigator对象简介Navigator对象包含有关浏览

    2025年8月29日
    5
  • leetcode 通配符匹配_部分匹配查询中有关通配符

    leetcode 通配符匹配_部分匹配查询中有关通配符给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。‘?’ 可以匹配任何单个字符。‘*’ 可以匹配任意字符串(包括空字符串)。两个字符串完全匹配才算匹配成功。说明:s 可能为空,且只包含从 a-z 的小写字母。p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。示例 1:输入:s = “aa”p = “a”输出: false解释: “a” 无法匹配 “aa” 整个字符串。示例 2:输入:s = “aa”p = “*

    2022年8月8日
    4
  • 超分辨率——基于SRGAN的图像超分辨率重建(Pytorch实现)[通俗易懂]

    超分辨率——基于SRGAN的图像超分辨率重建(Pytorch实现)[通俗易懂]基于SRGAN的图像超分辨率重建本文偏新手项,因此只是作为定性学习使用,因此不涉及最后的定量评估环节1简要介绍SRGAN的原论文发表于CVPR2017,即《Photo-RealisticSingleImageSuper-ResolutionUsingaGenerativeAdversarialNetwork》SRGAN使用了生成对抗的方式来进行图像的超分辨率重建,同时提出了一个由AdversarialLoss和ContentLoss组成的损失函数。更详细的介绍可以去看看

    2025年7月30日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号