原文地址:CompletableFuture原理与实践-外卖商家端API的异步化
CompletableFuture的介绍:
CompletableFuture是Java 8中引入的一种基于Future的异步编程机制。与传统的Future相比,CompletableFuture提供了更多的操作链支持,并且可以用灵活的方式来处理异步任务的结果,从而实现更加高效、简洁和优雅的异步编程。
CompletableFuture的主要特点包括:
-
方法链:CompletableFuture支持链式调用,即在每个方法返回CompletableFuture对象时,都可以继续调用后续方法,形成一个完整的方法链,从而实现对异步任务的串行或并行执行。
-
异常处理:CompletableFuture提供了非常好的异常处理机制,可以使用exceptionally或handle方法来抛出或捕获异常,并通过相应的回调函数进行处理。
-
结果聚合:CompletableFuture支持多个异步任务的聚合,即通过allOf或anyOf等方法来组合多个任务的结果,以及使用thenApplyAsync、thenCombine等方法进行结果的加工和归并。
-
灵活性:CompletableFuture还具有非常高的灵活性,可以结合Lambda表达式和函数式接口来实现更加优雅和简洁的异步编程方式。
总的来说,CompletableFuture是Java 8中非常重要的一种异步编程机制,它可以帮助我们提升系统的并发能力和响应性能,并且具有良好的可扩展性和可维护性。
CompletableFuture的简单使用
如下图所示,这里描绘的是一个业务接口的流程,其中包括CF1\CF2\CF3\CF4\CF5共5个步骤,并描绘了这些步骤之间的依赖关系,每个步骤可以是一次RPC调用、一次数据库操作或者是一次本地方法调用等,在使用CompletableFuture进行异步化编程时,图中的每个步骤都会产生一个CompletableFuture对象,最终结果也会用一个CompletableFuture来进行表示。
根据CompletableFuture依赖数量,可以分为以下几类:零依赖、一元依赖、二元依赖和多元依赖。
3.2.1 零依赖:CompletableFuture的创建
如上图红色链路所示,接口接收到请求后,首先发起两个异步调用CF1、CF2,主要有三种方式:
ExecutorService executor = Executors.newFixedThreadPool(5);
//1、使用runAsync或supplyAsync发起异步调用
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
return "result1";
}, executor);
//2、CompletableFuture.completedFuture()直接创建一个已完成状态的CompletableFuture
CompletableFuture<String> cf2 = CompletableFuture.completedFuture("result2");
//3、先初始化一个未完成的CompletableFuture,然后通过complete()、completeExceptionally(),完成该CompletableFuture
CompletableFuture<String> cf = new CompletableFuture<>();
cf.complete("success");
3.2.2 一元依赖:依赖一个CF
如上图红色链路所示,CF3,CF5分别依赖于CF1和CF2,这种对于单个CompletableFuture的依赖可以通过thenApply、thenAccept、thenCompose等方法来实现,代码如下所示:
CompletableFuture<String> cf3 = cf1.thenApply(result1 -> {
//result1为CF1的结果
//......
return "result3";
});
CompletableFuture<String> cf5 = cf2.thenApply(result2 -> {
//result2为CF2的结果
//......
return "result5";
});
3.2.3 二元依赖:依赖两个CF
如上图红色链路所示,CF4同时依赖于两个CF1和CF2,这种二元依赖可以通过thenCombine等回调来实现,如下代码所示:
CompletableFuture<String> cf4 = cf1.thenCombine(cf2, (result1, result2) -> {
//result1和result2分别为cf1和cf2的结果
return "result4";
});
3.2.4 多元依赖:依赖多个CF
如上图红色链路所示,整个流程的结束依赖于三个步骤CF3、CF4、CF5,这种多元依赖可以通过allOf
或anyOf
方法来实现,区别是当需要多个依赖全部完成时使用allOf
,当多个依赖中的任意一个完成即可时使用anyOf
,如下代码所示:
CompletableFuture<Void> cf6 = CompletableFuture.allOf(cf3, cf4, cf5);
CompletableFuture<String> result = cf6.thenApply(v -> {
//这里的join并不会阻塞,因为传给thenApply的函数是在CF3、CF4、CF5全部完成时,才会执行 。
result3 = cf3.join();
result4 = cf4.join();
result5 = cf5.join();
//根据result3、result4、result5组装最终result;
return "result";
});