SpringBoot-27- @Async实现异步调用 什么是异步调用

简介: 异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务。

SpringBoot-27- @Async实现异步调用

什么是异步调用


异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务


异步处理的方式:

  • Java异步处理:Thread/Runnable、Callable/Future
  • Servlet 3.0异步处理: asyncSupported、AsyncContext
  • Spring MVC异步处理: @Async、AsyncTaskExecutor


SpringBoot自身没有对异步调用做很大的变动,基本还是使用SpringMVC的@Async

开启异步调用配置

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
}


注解:在使用**@EnableWebMvc**注解的时候也可以开启异步调用,但是在SpringBoot中使用异步调用会使得SpringBoot的AutoConfig一部分功能失效。


定义线程池

定义一个或者多个线程池

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
    @Bean(name = "threadPoolTaskExecutor1")
    public Executor taskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor1-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
    @Bean(name = "threadPoolTaskExecutor2")
    public Executor threadPoolTaskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor2-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}



我们使用ThreadPoolTaskExecutor创建线程池,其参数配置如下:


CorePoolSize:设置核心线程数,线程池创建的时候创建线程的个数


MaxPoolSize:最大线程数,在换成队列满以后才会申请超过核心线程的线程


QueueCapacity:缓冲队列,用来缓冲执行任务的队列


KeepAliveSeconds:当超过了核心线程数之外的线程在空闲时间到达之后会被销毁


ThreadNamePrefix:线程名称前缀

定义异步调用方法

异步调用方法有两种一个是没有返回值的,一种是有返回值的,具体实现如下:

@Component
public class ComponentTask {
    public static Random random =new Random();
    /**
     * 无返回值
     */
    @Async("threadPoolTaskExecutor2")
    public void asyncMethodWithVoidReturnType_One() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(1000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_One,耗时:" + (end - start) + "毫秒"+"  threadname:"+Thread.currentThread().getName());
    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Two() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Two");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(2000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Two,耗时:" + (end - start) + "毫秒" +"  threadname:"+Thread.currentThread().getName());
    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Three() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Three");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(3000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Three,耗时:" + (end - start) + "毫秒"+ "  threadname:"+Thread.currentThread().getName());
    }
    /**
     * 有返回值的
     * @return
     */
    @Async("threadPoolTaskExecutor1")
    public Future<String> asyncMethodWithReturnType_One() throws InterruptedException {
        System.out.println("开始asyncMethodWithReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithReturnType_One,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务一完成");
    }
}


在多线程池的时候,我们需要在@Async()指定线程池名称**@Async(“threadPoolTaskExecutor1”)**

单元测试

@SpringBootTest
class SpringBootPart27ApplicationTests {
    @Autowired
    private ComponentTask componentTask;
    @Test
    void contextLoads() throws InterruptedException {
        componentTask.asyncMethodWithVoidReturnType_One();
        componentTask.asyncMethodWithVoidReturnType_Two();
        componentTask.asyncMethodWithVoidReturnType_Three();
        Thread.currentThread().join();
    }
}


在单元测试用例中,注入Task对象,并在测试用例中执行asyncMethodWithVoidReturnType_One、asyncMethodWithVoidReturnType_Two()、asyncMethodWithVoidReturnType_Three()三个函数。


执行结果如下:

开始做asyncMethodWithVoidReturnType_One
开始做asyncMethodWithVoidReturnType_Two
开始做asyncMethodWithVoidReturnType_Three
完成asyncMethodWithVoidReturnType_One,耗时:435毫秒  threadname:threadPoolTaskExecutor2-1
完成asyncMethodWithVoidReturnType_Two,耗时:1885毫秒  threadname:threadPoolTaskExecutor1-1
完成asyncMethodWithVoidReturnType_Three,耗时:1904毫秒  threadname:threadPoolTaskExecutor1-2


如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

目录
相关文章
|
3月前
|
Java 测试技术 Spring
Spring Boot使用@Async实现异步调用
Spring Boot使用@Async实现异步调用
23 0
|
6月前
|
Java API Spring
【Springboot】springboot 多线程@EnableAsync和@Async
【Springboot】springboot 多线程@EnableAsync和@Async
46 0
|
28天前
|
Java Spring
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
SpringBoot+async异步调用接口以及几个任务同时完成和异步接口实现和调用
24 0
|
1月前
|
监控 Java
【十一】springboot整合异步调用并获取返回值
【十一】springboot整合异步调用并获取返回值
38 0
|
3月前
|
Java Spring
SpringBoot @Async 注解
【1月更文挑战第1天】SpringBoot @Async 注解
|
4月前
|
Java Spring
使用spring boot的@Async实现异步调用和线程池复用
使用spring boot的@Async实现异步调用和线程池复用
|
4月前
|
Java Spring
SpringBoot - @Async异步任务与线程池
SpringBoot - @Async异步任务与线程池
68 1
|
6月前
|
Java 测试技术 Spring
Spring Boot + @Async =?
Spring Boot + @Async =?
33 0
|
7月前
|
安全 Java UED
SpringBoot 如何使用 @Async 注解处理异步事件
SpringBoot 如何使用 @Async 注解处理异步事件
|
21天前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源