上文我们主要写了CompletableFuture的基础用法,包括它是什么?如何创建?怎么使用?需要学习参考的可以参看如下文章:
本文我们主要讲述CompletableFuture高阶使用和用法,可以在项目参考灵活运用,配合线程池让代码更简单精巧。
我们都知道创建一个新的线程可以通过继承Thread类或者实现Runnable接口来实现,这两种方式创建的线程在运行结束后会被虚拟机销毁,进行垃圾回收,如果线程数量过多,频繁的创建和销毁线程会浪费资源,降低效率。而线程池的引入就很好解决了上述问题,线程池可以更好的创建、维护、管理线程的生命周期,做到复用,提高资源的使用效率,也避免了开发人员滥用new关键字创建线程的不规范行为。
一.使用ThreadPoolExecutor配置线程池
ThreadPoolExecutor是线程池的核心实现类,在JDK1.5引入,位于java.util.concurrent包,由Doug Lea完成,详细可参考如下文案:
线程池创建使用案例:
public static ExecutorService customThreadPool() {
return new ThreadPoolExecutor(
// 核心线程数
5,
// 最大线程数
20,
// 线程空闲时间
20,
// 线程空闲时间单位
TimeUnit.SECONDS,
// 线程队列
new LinkedBlockingQueue<>(20),
// 线程工厂
Executors.defaultThreadFactory(),
// 拒绝策略
new ThreadPoolExecutor.AbortPolicy());
}
二、使用CompletableFuture构建多线程异步查询案例
/**
*此处只展示核心代码,利用多线程异步查询拼接数据
**/
List<CompletableFuture<?>> futuresToJoin = new ArrayList<>();
CompletableFuture<List<AreaInfoEntity>> future1 =
CompletableFuture.supplyAsync(()->{
LambdaQueryWrapper<AreaInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AreaInfoEntity::getProjectid, pId);
return AreaInfoService.list(queryWrapper);
}, TestThreadPoolUtil.customThreadPool());
futuresToJoin.add(future1);
CompletableFuture<List<AreaInfoEntity>> future2 =
CompletableFuture.supplyAsync(() -> areaMapper.getAllAreaAlarmList(params), TestThreadPoolUtil.customThreadPool());
futuresToJoin.add(future2);
//返回值为空
CompletableFuture<Void> future3 =
CompletableFuture.runAsync(() -> {
System.currentTimeMillis();
}, TestThreadPoolUtil.customThreadPool());
futuresToJoin.add(future3);
//统一执行查询
CompletableFuture<Void> allFutures = CompletableFuture.allOf(futuresToJoin.toArray(new CompletableFuture<?>[0]));
allFutures.join();
//获取执行结果
List<AreaInfoEntity> areaList = future1.get();
Map<String, AreaInfoEntity> areaInfoEntityMap = future2.get().stream()
.collect(Collectors.toMap(ServDefenceAreaInfoEntity::getId,
Function.identity(), (key1, key2) -> key2));