将多个 CompletableFuture 应用于另一个 CompletableFuture 的结果的最佳方法是什么?

What is the best way to apply more than one CompletableFuture on result of another CompletableFuture?

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

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

loadAndApply 结合了所有其他方法。 loadData长期获取数据。然后我们将 someObject.A 设置为 运行ning processA(data) 的结果并将 someObject.B 设置为 运行ning 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 更好的方法,它实际上不对给定对象应用任何东西,只是 returns 它用于下一个未来?

您可以使用 CompletionStage.thenCompose(Function) in combination with CompletableFuture.allOf(CompletableFuture...) 来完成此操作。 thenCompose 使用的 Function 的通用签名是: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:

Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete. If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a CompletionException holding this exception as its cause. Otherwise, the results, if any, of the given CompletableFutures are not reflected in the returned CompletableFuture, but may be obtained by inspecting them individually. If no CompletableFutures are provided, returns a CompletableFuture completed with the value null.

Among the applications of this method is to await completion of a set of independent CompletableFutures before continuing a program, as in: CompletableFuture.allOf(c1, c2, c3).join();.

...以及 thenCompose 的 Javadoc:

Returns a new CompletionStage that is completed with the same value as the CompletionStage returned by the given function.

When this stage completes normally, the given function is invoked with this stage's result as the argument, returning another CompletionStage. When that stage completes normally, the CompletionStage returned by this method is completed with the same value.

To ensure progress, the supplied function must arrange eventual completion of its result.

This method is analogous to Optional.flatMap and Stream.flatMap.

See the CompletionStage documentation for rules covering exceptional completion.

注意:CompletableFuture 实现了 CompletionStage,覆盖了 thenCompose 但使 return 类型更具体(returns CompletableFuture 而不是 CompletionStage).