问题描述
如果有 2 个 CompletionStages,我可以将它们与 thenCombine
方法结合起来:
If have 2 CompletionStages, I can combine them with thenCombine
method:
CompletionStage<A> aCompletionStage = getA();
CompletionStage<B> bCompletionStage = getB();
CompletionStage<Combined> combinedCompletionStage =
aCompletionStage.thenCombine(bCompletionStage, (aData, bData) -> combine(aData, bData));
如果我有 3 个或更多 CompletionStages,我可以创建一个 thenCombine
方法链,但我必须使用临时对象来传递结果.例如,这是一个使用 org.apache.commons.lang3.tuple
包中的 Pair
和 Triple
的解决方案:
If I have 3 or more CompletionStages, I can make a chain of thenCombine
methods, but I have to use temporary objects to pass results. For example, here is a solution using Pair
and Triple
from the org.apache.commons.lang3.tuple
package:
CompletionStage<A> aCompletionStage = getA();
CompletionStage<B> bCompletionStage = getB();
CompletionStage<C> cCompletionStage = getC();
CompletionStage<D> dCompletionStage = getD();
CompletionStage<Combined> combinedDataCompletionStage =
aCompletionStage.thenCombine(bCompletionStage, (Pair::of))
.thenCombine(cCompletionStage, (ab, c) ->
Triple.of(ab.getLeft(), ab.getRight(), c))
.thenCombine(dCompletionStage, (abc, d) ->
combine(abc.getLeft(), abc.getMiddle(), abc.getRight(), d));
是否有更好的方法来组合多个 CompletionStages 的结果?
Is there a better way to combine results from multiple CompletionStages?
推荐答案
结合多个阶段的唯一方法是使用 CompletableFuture
.如果你的 CompletionStage
不是 CompletableFuture
你仍然可以使用 .toCompletableFuture()
转换它们:
The only way to combine multiple stages that scales well with a growing number of stages, is to use CompletableFuture
. If your CompletionStage
s aren’t CompletableFuture
s you may still convert them using .toCompletableFuture()
:
CompletableFuture<A> aCompletionStage = getA().toCompletableFuture();
CompletableFuture<B> bCompletionStage = getB().toCompletableFuture();
CompletableFuture<C> cCompletionStage = getC().toCompletableFuture();
CompletableFuture<D> dCompletionStage = getD().toCompletableFuture();
CompletionStage<Combined> combinedDataCompletionStage = CompletableFuture.allOf(
aCompletionStage, bCompletionStage, cCompletionStage, dCompletionStage)
.thenApply(ignoredVoid -> combine(
aCompletionStage.join(), bCompletionStage.join(),
cCompletionStage.join(), dCompletionStage.join()) );
这包含比通过 thenCombine
组合两个阶段更多的样板,但在向其中添加更多阶段时样板不会增长.
This contains more boilerplate than combining two stages via thenCombine
but the boilerplate doesn’t grow when adding more stages to it.
请注意,即使使用原始的 thenCombine
方法,您也不需要 Triple
,一个 Pair
就足够了:
Note that even with your original thenCombine
approach, you don’t need a Triple
, a Pair
is sufficient:
CompletionStage<Combined> combinedDataCompletionStage =
aCompletionStage.thenCombine(bCompletionStage, (Pair::of)).thenCombine(
cCompletionStage.thenCombine(dCompletionStage, Pair::of),
(ab, cd) -> combine(ab.getLeft(), ab.getRight(), cd.getLeft(), cd.getRight()));
不过,如果您想组合更多阶段,它的扩展性并不好.
Still, it doesn’t scale well if you want to combine more stages.
中间解决方案(关于复杂性)可能是:
An in-between solution (regarding complexity) might be:
CompletionStage<Combined> combinedDataCompletionStage = aCompletionStage.thenCompose(
a -> bCompletionStage.thenCompose(b -> cCompletionStage.thenCompose(
c -> dCompletionStage.thenApply(d -> combine(a, b, c, d)))));
它的结构更简单,但仍然不能很好地扩展更多阶段.
That’s simpler in its structure but still doesn’t scale well with more more stages.
这篇关于如何组合 3 个或更多 CompletionStages?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!