一、前言
环境:SpringBoot 2.1.5.RELEASE
需求:java中使用多线程异步,想要有顺序的拿到最后的结果并进行接口返回。
二.线程池配置
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setKeepAliveSeconds(300);
pool.setCorePoolSize(5);//核心线程池数
pool.setMaxPoolSize(10); // 最大线程
pool.setQueueCapacity(100);//队列容量
pool.setAwaitTerminationSeconds(1);
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //队列满,线程被拒绝执行策略
pool.setWaitForTasksToCompleteOnShutdown(true);
pool.setAwaitTerminationSeconds(1);
return pool;
}
}
三.控制器
@RequestMapping("/findAsyncData")
public Object findAsyncData() {
List<UserLocal> list = dataThreadService.findAsyncData();
return list;
}
四.Service接口实现
public List<UserLocal> findAsyncData() {
List<CustomRunnable> list = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(40);
for (int i = 1; i < 41; i++) {
CustomRunnable customRunnable = new CustomRunnable(i, latch);
list.add(customRunnable);
}
list.forEach(o -> {
executor.threadPoolTaskExecutor().execute(o);
});
AtomicInteger result = new AtomicInteger();
List<UserLocal> userLocalList = new ArrayList<>();
try {
// latch.await();
latch.await(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
list.forEach(o -> {
userLocalList.add(o.findUserLocal());
System.out.println("循环结果"+o.findUserLocal());
});
return userLocalList;
}
五.自定义多线程类
final class CustomRunnable implements Runnable {
public CustomRunnable() {
}
private int userId = 0;
private UserLocal userLocal;
private CountDownLatch countDownLatch;
public CustomRunnable(int id, CountDownLatch latch) {
userId = id;
countDownLatch = latch;
}
public void run() {
long start = System.currentTimeMillis();
userLocal = userLocalMapper.selectByPrimaryKey(userId);
System.out.println("多线程结果"+userLocal);
long time = System.currentTimeMillis() - start;
System.out.println(userId + Thread.currentThread().getName() + ":执行 end 耗时:" + time + "ms");
countDownLatch.countDown();
}
//获取结果
private UserLocal findUserLocal() {
return userLocal;
}
}
六.总结
上面的逻辑是从控制器带service的整个逻辑实现,其中原理就是利用线程池实现异步多线程调用方法,最后利用闭锁CountDownLatch完成了线程的整个等待结果的过程,最后实现有序结果的放回。