Spring Boot中调用@Async注解的异步方法并获取返回值
该方法无需创建任何实体,只需要通过传参即可获取返回结果
需求背景
最近正在研发的系统有接口需要从多个表中获取数据进行处理,所以打算使用多线程异步获取到这几个表处理后的数据结果。由于Spring Boot提供多线程ThreadPoolTaskExecutor类,使用代码如下
代码
配置类
@Configuration public class ThreadPoolConfig { @Value("${threadpool.core-pool-size}") private int corePoolSize; @Value("${threadpool.max-pool-size}") private int maxPoolSize; @Value("${threadpool.queue-capacity}") private int queueCapactiy; @Value("${threadpool.keep-alive-seconds}") private int keepAliveSeconds; // 配置线程前缀 @Value("${threadpool.name-prefix}") private String namePrefix; @Bean("taskExecutor") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds); threadPoolTaskExecutor.setCorePoolSize(corePoolSize); threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize); threadPoolTaskExecutor.setQueueCapacity(queueCapactiy); threadPoolTaskExecutor.setThreadNamePrefix(namePrefix); threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); threadPoolTaskExecutor.initialize(); return threadPoolTaskExecutor; } }
配置文件
# 多线程 threadpool.core-pool-size=xx threadpool.max-pool-size=xx threadpool.queue-capacity=xxx threadpool.keep-alive-seconds=xxx threadpool.name-prefix=taskExecutorInitData
启动类上加注解
@EnableAsync
业务逻辑代码
@Autowired MedicalServiceService medicalServiceService; public void initData(String personId) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(4); // 就诊数据 List<DataVisitBasicDo> visitBasic = new ArrayList<>(); medicalServiceService.getVisitBasicFromBigData(visitBasic, countDownLatch); // 检查数据 List<DataVisitExamDo> visitExam = new ArrayList<>(); medicalServiceService.getVisitExamFromBigData(visitExam, countDownLatch); }
异步方法
@Async("taskExecutor") public void getVisitBasicFromBigData( List<DataVisitBasicDo> visitBasicFromBigData,CountDownLatch countDownLatch) { // 从数据库中查出来的集合数据 List<DataVisitBasicBigDo> lists = dataVisitBigDataDao.getTest1(); // 处理过程...... visitExamFromBigData.addAll(lists); // 该代码无效 // visitExamFromBigData = lists countDownLatch.countDown(); } @Async("taskExecutor") public void getVisitExamFromBigData( List<DataVisitExamDo> visitExamFromBigData, CountDownLatch countDownLatch) { // 从数据库中查出来的集合数据 List<DataVisitExamBigDo> lists = dataVisitBigDataDao.getTest2(); // 处理过程...... visitExamFromBigData.addAll(lists); // 该代码无效 // visitExamFromBigData = lists countDownLatch.countDown(); }
不可与调用方在同一个类中,否则异步调用无效,是串行执行
注意:
想要获取异步方法中处理后的数据结果,可以直接通过传参进行接收,众所周知,引用类型传参传的是地址,我们可以根据参数地址对应的对象集合进行add操作,这样就可以把异步处理的数据结果返回给主线程了。
那为什么直接用等于号就回失效呢?
visitExamFromBigData = lists,lists对象所在地址会替换掉原本的参数地址,所以主线程中的集合并没有发生变化。如下图所示
下一篇:
File类(文件和目录的创建与删除)