温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

SpringBoot中异步调用@Async的方法

发布时间:2021-07-08 17:15:32 来源:亿速云 阅读:187 作者:chen 栏目:web开发

本篇内容主要讲解“SpringBoot中异步调用@Async的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot中异步调用@Async的方法”吧!

如何开启异步调用

在SpringBoot中,只需要给方法加上@Async注解,就能将同步方法变为异步调用。

首先在启动类上添加@EnableAsync,即开启异步调用。

/**  * @author qcy  */ @SpringBootApplication @EnableAsync public class AsyncApplication {      public static void main(String[] args) {         SpringApplication.run(AsyncApplication.class, args);     }  }

在需要异步调用的方法上加上@Async注解

package com.yang.async;  import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component;  import java.util.concurrent.Future; import java.util.concurrent.FutureTask;  /**  * @author qcy  * @create 2020/09/09 14:01:35  */ @Slf4j @Component public class Task {      @Async     public void method1() {         log.info("method1开始,执行线程为" + Thread.currentThread().getName());         try {             Thread.sleep(2000);         } catch (InterruptedException e) {             e.printStackTrace();         }         log.info("method1结束");     }      @Async     public void method2() {         log.info("method2开始,执行线程为" + Thread.currentThread().getName());         try {             Thread.sleep(3000);         } catch (InterruptedException e) {             e.printStackTrace();         }         log.info("method2结束");     }   }

测试一下:

@SpringBootTest @Slf4j public class AsyncApplicationTests {      @Autowired     Task task;      @Test     public void testAsyncWithVoidReturn() throws InterruptedException {         log.info("main线程开始");          task.method1();         task.method2();          //确保两个异步调用执行完成         Thread.sleep(6000);          log.info("main线程结束");     }  }

输出如下:

SpringBoot中异步调用@Async的方法

可以看得出,SpringBoot创建了一个名为applicationTaskExecutor的线程池,使用这里面的线程来执行异步调用。

这里值得注意的是,不要在一个类中调用@Async标注的方法,否则不会起到异步调用的作用,至于为什么会产生这样的问题,需要深入到源码中一探究竟,会另开篇幅。

既然默认使用的是SpringBoot自己创建的applicationTaskExecutor,那如何自己去定义一个线程池呢?

自定义线程池

我们需要手动创建一个名为asynTaskExecutord的Bean

package com.yang.async;  import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  import java.util.concurrent.ThreadPoolExecutor;  /**  * @author qcy  * @create 2020/09/09 15:31:07  */ @Slf4j @Configuration public class AsyncConfig {      @Bean     public AsyncTaskExecutor asyncTaskExecutor() {         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();         executor.setCorePoolSize(8);         executor.setMaxPoolSize(16);         executor.setQueueCapacity(50);         executor.setAllowCoreThreadTimeOut(true);         executor.setKeepAliveSeconds(10);         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());         executor.setThreadNamePrefix("async-thread-pool-thread");         return executor;     } }

对以上参数不了解的同学,可以参考我的这篇文章说说线程池

其他类不需要变动,直接运行刚才的testAsyncWithVoidReturn()方法,输出:

SpringBoot中异步调用@Async的方法

看得出来,现在是我们自定义的线程池

如果关心异步调用的返回值,又怎么处理?

获取异步调用的返回结果

获取异步调用的结果,需要利用Future机制,可以参考我的另外一篇文章谈谈Runnable、Future、Callable、FutureTask之间的关系

为Task类增加以下两个方法:

@Async   public Future<String> method3() {       log.info("method3开始,执行线程为" + Thread.currentThread().getName());       try {           Thread.sleep(1000);       } catch (InterruptedException e) {           e.printStackTrace();       }       log.info("method3结束");       return new AsyncResult<>("method3");   }    @Async   public Future<String> method4() {       log.info("method4开始,执行线程为" + Thread.currentThread().getName());       try {           Thread.sleep(3000);       } catch (InterruptedException e) {           e.printStackTrace();       }       log.info("method4结束");       return new AsyncResult<>("method4");   }

测试类:

@Test   public void testAsyncWithStringReturn() throws InterruptedException, ExecutionException {       log.info("main线程开始");        Future<String> method3Result = task.method3();       Future<String> method4Result = task.method4();        //get方法为阻塞获取       log.info("method3执行的返回结果:{}", method3Result.get());       log.info("method4执行的返回结果:{}", method4Result.get());       log.info("main线程结束");   }

输出:

SpringBoot中异步调用@Async的方法

springboot是什么

springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。

到此,相信大家对“SpringBoot中异步调用@Async的方法”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI