让我们举一个例子:
我们有四种方法:

CompletableFututre<Void> loadAndApply(SomeObject someObject);
CompletableFuture<SomeData> loadData();
A processA(SomeData data);
B processB(SomeData data);


loadAndApply结合了所有其他方法。 loadData长时间获取数据。然后,将someObject.A设置为运行processA(data)的结果,并将someObject.B设置为运行processB(data)的结果
我们不能同时应用processAprocessB,因为processA只能在swingExecutor上运行,而processB只能在backgroundExecutor上运行。

所以我的问题是:我们可以以某种美观的方式将所有这些方法链接起来吗?

目前,我像这样启动它们:

CompletableFututre<Void> loadAndApply(SomeObject someObject) {
    return loadData()
      .thenApplyAsync(data -> { someObject.setA(processA(data)); return data; }, swingExecutor)
      .thenAcceptAsync(data -> someObject.setB(processB(data)), backgroundExecutor);
}


有什么方法看起来比applyAsync更好,实际上没有对给定对象应用任何内容,只是在下一个将来返回它?

最佳答案

您可以通过将CompletionStage.thenCompose(Function)CompletableFuture.allOf(CompletableFuture...)结合使用来实现。 Function使用的thenCompose的通用签名为:Function<? super T, ? extends CompletionStage<U>>

public CompletableFuture<Void> loadAndApply(SomeObject object) {
  return loadData().thenCompose(data ->
      CompletableFuture.allOf(
          CompletableFuture.runAsync(() -> object.setA(processA(data)), swingExecutor),
          CompletableFuture.runAsync(() -> object.setB(processB(data)), backgroundExecutor)
      ) // End of "allOf"
  ); // End of "thenCompose"
} // End of "loadAndApply"


这有一个额外的好处。在当前使用thenAcceptAsync阶段的代码中,必须等待thenApplyAsync阶段完成才能执行。当使用以上代码时,setAsetB都将在各自的执行程序中同时运行。

为了方便起见,以下是allOf的Javadoc:


  返回一个新的CompletableFuture,当所有
  给定CompletableFutures完成。如果给定的任何
  CompletableFutures异常完成,然后返回
  CompletableFuture也这样做,持有CompletionException
  此异常是其原因。否则,如果有的话,
  给定的CompletableFutures不反映在返回的值中
  CompletableFuture,但可以通过检查它们来获得
  个别地。如果未提供CompletableFutures,则返回
  CompletableFuture已完成,值为null。
  
  该方法的应用之一是等待一组完成
  在继续执行程序之前,先确定独立的CompletableFutures,如:
  CompletableFuture.allOf(c1,c2,c3).join();。


...以及thenCompose的Javadoc:


  返回一个新的CompletionStage,其值与
  给定函数返回的CompletionStage。
  
  当此阶段正常完成时,将使用
  这个阶段的结果作为参数,返回另一个
  CompletionStage。该阶段正常完成后,
  此方法返回的CompletionStage用相同的方法完成
  值。
  
  为了确保进度,提供的功能必须安排最终的
  完成其结果。
  
  此方法类似于Optional.flatMap和Stream.flatMap。
  
  有关涵盖特殊情况的规则,请参见CompletionStage文档。
  完成。


注意:实现CompletableFutureCompletionStage会覆盖thenCompose,但会使返回类型更具体(返回CompletableFuture而不是CompletionStage)。

09-15 13:54