文章目录
- 一. 合并两个异步任务的结果
- 1. `thenCombine()`:组合两个异步任务的结果
- 2. `runAfterBoth()`:在两个任务完成后执行无返回值操作
- 3. `thenAcceptBoth()`:消费两个任务的结果
- 二. `allOf()`:等待所有任务完成
如果某个任务同时依赖另外两个异步任务的执行结果,就需要对另外两个异步任务进行合并。以泡茶喝为例,“泡茶喝”任务需要对“烧水”任务与“清洗”任务进行合并。
对两个异步任务的合并可以通过CompletionStage接口的thenCombine()、runAfterBoth()、thenAcceptBoth()三个方法来实现。
一. 合并两个异步任务的结果
1.thenCombine():组合两个异步任务的结果
thenCombine()方法允许我们同时处理两个异步任务的结果。当这两个任务都完成时,它会执行一个BiFunction,将两个任务的结果组合起来,并返回一个新的CompletableFuture,该CompletableFuture包含组合后的结果。
使用场景:当你有两个异步任务,且需要同时使用它们的结果来进行某些操作时,thenCombine()非常适合。
示例代码:
CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(()->2);CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(()->3);future1.thenCombine(future2,(result1,result2)->result1+result2).thenAccept(result->System.out.println(result));// 输出 5**分析**:-`future1` 和 `future2` 是两个异步任务,分别返回 `2` 和 `3`。-`thenCombine()` 会将这两个结果相加,并返回 `5`。-`thenAccept()` 最终打印出 `5`。例子2:
@TestpublicvoidthenCombineDemo()throwsException{CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(newSupplier<Integer>(){@OverridepublicIntegerget(){IntegerfirstStep=10+10;Print.tco("firstStep outcome is "+firstStep);returnfirstStep;}});CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(newSupplier<Integer>(){@OverridepublicIntegerget(){IntegersecondStep=10+10;Print.tco("secondStep outcome is "+secondStep);returnsecondStep;}});CompletableFuture<Integer>future3=future1.thenCombine(future2,newBiFunction<Integer,Integer,Integer>(){@OverridepublicIntegerapply(Integerstep1OutCome,Integerstep2OutCome){returnstep1OutCome*step2OutCome;}});Integerresult=future3.get();Print.tco(" outcome is "+result);}2.runAfterBoth():在两个任务完成后执行无返回值操作
runAfterBoth()方法会在两个异步任务都完成后执行一个没有返回值的操作。与thenCombine()不同,它不关心这两个任务的结果,而是专注于在它们都完成后做某些操作(比如记录日志、更新状态等)。
使用场景:
当你希望在两个异步任务都完成后执行某些副作用操作,但不关心它们的计算结果时,runAfterBoth()是最理想的选择。
示例代码:
CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(()->2);CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(()->3);future1.runAfterBoth(future2,()->System.out.println("Both tasks completed"));// 输出 "Both tasks completed"**分析**:-`runAfterBoth()` 会在 `future1` 和 `future2` 都完成后执行,无返回值的操作,这里是打印出"Both tasks completed"。-重要的是,它不会使用 `future1` 和 `future2` 的结果,而仅在它们都完成时执行某个动作。3.thenAcceptBoth():消费两个任务的结果
thenAcceptBoth()方法会在两个异步任务都完成后,执行一个BiConsumer,将这两个任务的结果作为参数传递给消费操作。它适用于在多个任务完成后需要处理这些结果的场景。
使用场景:
当你希望在两个任务都完成时,同时处理它们的结果,但不需要返回任何新的结果时,thenAcceptBoth()非常适用。
示例代码:
CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(()->2);CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(()->3);future1.thenAcceptBoth(future2,(result1,result2)->System.out.println("Result1: "+result1+", Result2: "+result2));// 输出 "Result1: 2, Result2: 3"**分析**:-`thenAcceptBoth()` 会在 `future1` 和 `future2` 都完成后,执行 `BiConsumer`,并将两个任务的结果传入。-这里,我们打印出 `Result1:2` 和 `Result2:3`,显示了两个任务的计算结果。二.allOf():等待所有任务完成
allOf()方法接受多个CompletableFuture作为参数,并返回一个新的CompletableFuture<Void>,该CompletableFuture在所有输入的任务都完成时才完成。它通常用于等待多个异步任务全部完成,并且不关心它们的结果。
使用场景:
当你有多个异步任务,并且你希望在它们都完成时继续执行某些操作,而不需要关心每个任务的结果时,可以使用allOf()。这是一个非常常用的场景,特别是在执行多个独立的异步任务时。
示例代码:
CompletableFuture<Integer>future1=CompletableFuture.supplyAsync(()->2);CompletableFuture<Integer>future2=CompletableFuture.supplyAsync(()->3);CompletableFuture<Integer>future3=CompletableFuture.supplyAsync(()->4);CompletableFuture<Void>allOf=CompletableFuture.allOf(future1,future2,future3);allOf.thenRun(()->System.out.println("All tasks are completed"));// 输出 "All tasks are completed"**分析**:-`allOf()` 会等待 `future1`、`future2` 和 `future3` 全部完成。-`thenRun()` 会在所有任务完成后执行,并输出"All tasks are completed"。-需要注意的是,`allOf()` 返回的 `CompletableFuture<Void>` 不关心每个任务的计算结果,只关注所有任务是否完成。thenRun用于在当前CompletableFuture完成后执行一个没有返回值的操作。它的作用类似于回调机制,但不同于常规的回调函数,thenRun()不接受任务的结果作为输入,它只是执行一个副作用操作(例如打印日志、更新状态等)。
例子2:
@TestpublicvoidallOfDemo()throwsException{CompletableFuture<Void>future1=CompletableFuture.runAsync(()->Print.tco("模拟异步任务1"));CompletableFuture<Void>future2=CompletableFuture.runAsync(()->Print.tco("模拟异步任务2"));CompletableFuture<Void>future3=CompletableFuture.runAsync(()->Print.tco("模拟异步任务3"));CompletableFuture<Void>future4=CompletableFuture.runAsync(()->Print.tco("模拟异步任务4"));CompletableFuture<Void>all=CompletableFuture.allOf(future1,future2,future3,future4);all.join();}
join()方法与get()类似,但是它不会抛出InterruptedException或ExecutionException。相反,如果任务失败,join()会抛出CompletionException,这意味
着我们需要通过join()等待所有任务完成,并且如果有任务失败,CompletionException会包装抛出异常。