Springboot @Async 多线程获取返回值
需求背景
最近需要用到多线程, 自己维护线程池很麻烦, 正好看到Springboot
集成线程池的例子, 这里自己做了个尝试和总结, 记录一下, 也分享给需要的朋友;
不考虑事务的情况下, 这个多线程实现比较简单, 主要有以下几点:
- 在启动类加上
@EnableAsync
注解, 开启异步执行支持; - 编写线程池配置类, 别忘了
@Configuration
, 和@Bean
注解; - 编写需要异步执行的业务, 放到单独的类中 (可以定义为 service, 因为需要 spring 管理起来才能用 );
举栗个现实问题:
需求 :拉取 业务数据不能超过 5秒。
拉取第三方数据 ,分别需要拉取 A业务数据(需要2秒) 、拉取 B业务数据(需要2秒)、拉取 C业务数据(需要2秒) ,最后再一并返回给前端。
解决方案 : Executor
+@Async("参数")
+CompletableFuture
或 Future
上代码
1.启动类上加注解
java
@EnableAsync
2.配置类
其他配置请参考配置类示例
java
@Slf4j
//@EnableAsync//(该注解加在启动类或线程池配置类上都可以)
@Configuration
public class ThreadPoolCommonConfig extends AsyncConfigurerSupport {
@Bean("asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(20);
taskExecutor.setMaxPoolSize(100);
taskExecutor.setQueueCapacity(1000);
taskExecutor.setKeepAliveSeconds(60);
taskExecutor.setThreadNamePrefix("asyncExecutorConfig--");
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(60);
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// MDC 装饰器 传递MDC中的信息
taskExecutor.setTaskDecorator(new MdcTaskDecorator());
return taskExecutor;
}
}
3.异步方法(所属类需交由Spring管理)
3.1.@Async + CompletableFuture(推荐)
java
@Override
@Async("asyncExecutor")
public CompletableFuture<String> list(String s) {
log.info("{}: {}", s, Thread.currentThread().getName());
ThreadUtil.sleep(2, TimeUnit.SECONDS);
log.info("{}查询列表成功", s);
return CompletableFuture.completedFuture(s);
}
3.2.@Async + Future
java
// 异步执行的方法, 注解内为自定义线程池类名
@Override
@Async("asyncExecutor")
public Future<Integer> test(Integer i) {
log.info("{}: {}", i, Thread.currentThread().getName());
ThreadUtil.sleep(1, TimeUnit.SECONDS);
log.info("@Async执行:{}", i);
return new AsyncResult(i);
}
4.调用
4.1.CompletableFuture获取返回值(推荐)
java
CompletableFuture<String> future1 = testService.list("A");
CompletableFuture<String> future2 = testService.list("B");
// 阻塞所有异步线程执行完毕
CompletableFuture.allOf(future1, future2).join();
// 阻塞,直至 future1 和 future2 的异步线程执行完毕
log.info("future结果:{},{}", future1.get(), future2.get());
4.2.Future获取返回值
java
Future<Integer> future1 = testService.test(1);
Future<Integer> future2 = testService.test(2);
// 阻塞,直至 future1 的异步线程执行完毕
log.info("future1结果:{}", future1.get());
// 阻塞,直至 future2 的异步线程执行完毕
log.info("future1结果:{}", future2.get());
参考文档
Async注解使用和CompletableFuture注解获取返回值
Springboot @Async 多线程获取返回值
Spring Boot中调用@Async注解的异步方法并获取返回值