很多时候多个任务之间的业务逻辑上处理存在串行[依赖]、并行、聚合的关系。CompletableFuture是Future接口的增强,实现了对任务的编排能力。
CompletionStage接口:执行某一个阶段,可向下执行后续阶段。
使用demo:
CompletableFuture<String> future =CompletableFuture.supplyAsync(()‐>{System.out.println("执行有返回值的异步任务");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}return "Hello World";});//join()和get()方法都是用来获取CompletableFuture异步之后的返回值String result=future.get();System.out.println(result);//当CompletableFuture的计算结果完成,可以执行特定的 Action。future.whenComplete(new BiConsumer<String, Throwable>() {@Overridepublic void accept(String t, Throwable action) {System.out.println(t+" 执行完成!");}});//抛出异常的时候,可以执行特定的Action。future.exceptionally(new Function<Throwable, String>() {@Overridepublic String apply(Throwable t) {System.out.println("执行失败:"+t.getMessage());return "异常xxxx";}}).join();
应用场景
依赖关系:
- thenApply() 把前面异步任务的结果,交给后面的Function
thenCompose()用来连接两个有依赖关系的任务,结果由第二个任务返回
and聚合关系:
thenCombine:任务合并,有返回值
- thenAccepetBoth:两个任务执行完成后,将结果交给thenAccepetBoth消耗,无返回值。
runAfterBoth:两个任务都执行完成后,执行下一步操作(Runnable)。
or聚合关系:
applyToEither:两个任务谁执行的快,就使用那一个结果,有返回值。
- acceptEither: 两个任务谁执行的快,就消耗那一个结果,无返回值。
- runAfterEither: 任意一个任务执行完成,进行下一步操作(Runnable)。
并行执行:
CompletableFuture类自己也提供了anyOf()和allOf()用于支持多个CompletableFuture 并行执行

使用案例:实现最优的“烧水泡茶”程序

对于烧水泡茶这个程序,一种最优的分工方案:用两个线程 T1 和 T2 来完成烧水泡茶程序, T1 负责洗水壶、烧开水、泡茶这三道工序,T2 负责洗茶壶、洗茶杯、拿茶叶三道工序,其中 T1 在执行泡茶这道工序时需要等待 T2 完成拿茶叶的工序。
public class CompletableFutureDemo2 {public static void main(String[] args) {//任务1:洗水壶‐>烧开水CompletableFuture<Void> f1=CompletableFuture.runAsync(() ‐>{System.out.println("T1:洗水壶...");sleep(1, TimeUnit.SECONDS);System.out.println("T1:烧开水...");sleep(15, TimeUnit.SECONDS);});//任务2:洗茶壶‐>洗茶杯‐>拿茶叶CompletableFuture<String> f2=CompletableFuture.supplyAsync(() ‐> {System.out.println("T2:洗茶壶...");sleep(1, TimeUnit.SECONDS);System.out.println("T2:洗茶杯...");sleep(2, TimeUnit.SECONDS);System.out.println("T2:拿茶叶...");sleep(1, TimeUnit.SECONDS);return "龙井";});//任务3:任务1和任务2完成后执行:泡茶CompletableFuture<String> f3 = f1.thenCombine(f2, (__, tf)‐>{System.out.println("T1:拿到茶叶:"+tf);System.out.println("T1:泡茶...");return "上茶:"+tf;});//等待任务3执行结果System.out.println(f3.join());}
