1.前言
CompletableFuture的使用非常灵活,其用法特别多,包括创建异步任务、异步回调、组合处理等,能够大大提高程序的执行效率,充分调度好系统资源完成我们的功能需求。
2.主角CompletableFuture
CompletableFuture实际还是使用异步多线程的方式帮助我们提高代码的执行效率,相比于上期说的parallelStream更加灵活,可以完成更加复杂的业务
3.CompletableFuture实际用法
先介绍一下目前实际需要优化的业务,项目中有快代码需要去读取多个文件数据进行数据处理,原本是一个一个取出来汇总,然后遍历处理,由于使用的是单线程处理,存在效率低下,响应时间过长问题。
优化思路:使用CompletableFuture异步多线程处理任务,将一个文件的处理添加到线程池中进行,这样我们业务的处理就由线程池的线程进行处理,等待所有任务读取完毕再统一做数据处理
代码:
import java.util.Map;
import java.util.concurrent.*;
public class TestCompletableFuture {
//根据业务定义线程池
private static ExecutorService executor = new ThreadPoolExecutor(50, 2000, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100000));
public static void main(String[] args) throws ExecutionException, InterruptedException {
Map<Integer, CompletableFuture<Integer>> data = new ConcurrentHashMap<>();
long time1 = System.currentTimeMillis();
//模拟一百次业务处理
for (int i=0;i<100;i++){
final int j = i;
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() ->{
try {
//返回执行结果
return doBussness(j);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
},executor);
data.put(i,completableFuture);
}
CompletableFuture<Integer>[] objects = new CompletableFuture[data.size()];
int i = 0;
for (Map.Entry<Integer, CompletableFuture<Integer>> integerCompletableFutureEntry : data.entrySet()) {
objects[i] = integerCompletableFutureEntry.getValue();
i++;
}
//等待所以业务处理完毕
CompletableFuture.allOf(objects).join();
System.out.println("总耗时"+(System.currentTimeMillis() - time1));
//输出所有处理结果
for (CompletableFuture<Integer> completableFuture : objects){
System.out.println(completableFuture.get());
}
}
//模拟业务处理
private static int doBussness(int i) throws InterruptedException {
//模拟处理耗时3s
TimeUnit.SECONDS.sleep(3);
return i;
}
}
4.代码运行结果
总耗时6049
5.CompletableFuture使用说明
例子中使用了CompletableFuture.supplyAsync()方法,该方法是有返回值的,有返回值对应就有无返回值方法CompletableFuture.runAsync(),CompletableFuture的用法特别多,还有thenApply、thenApplyAsync、thenAccept等,而且还有一些任务之间的组合api,例如thenCombine 、 thenAcceptBoth 、 runAfterBoth等,可以帮助我们实现一下复杂且有层级递进的任务,CompletableFuture详细的介绍可以点击传送门。
6.总结
从结果看,如果是单线程处理的话需要的时间则是100*3=300s的时间,通过优化之后发现,只需要6秒多就完成了,优化后的效果十分明显。