如何组合 3 个或更多完成阶段?

2022-09-01 05:47:53

如果有2个完成阶段,我可以将它们与方法相结合:thenCombine

CompletionStage<A> aCompletionStage = getA();
CompletionStage<B> bCompletionStage = getB();
CompletionStage<Combined> combinedCompletionStage =
    aCompletionStage.thenCombine(bCompletionStage, (aData, bData) -> combine(aData, bData));

如果我有 3 个或更多 FinishStages,我可以创建一个方法链,但我必须使用临时对象来传递结果。例如,下面是使用和从包中执行的解决方案:thenCombinePairTripleorg.apache.commons.lang3.tuple

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));

有没有更好的方法来合并来自多个完成阶段的结果?


答案 1

将多个阶段与越来越多的阶段很好地结合在一起的唯一方法是 使用 。如果你的 s 不是 s,你仍然可以使用 :CompletableFutureCompletionStageCompletableFuture.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


请注意,即使使用原始方法,也不需要 ,a 就足够了:thenCombineTriplePair

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()));

尽管如此,如果你想组合更多的阶段,它不能很好地扩展。


介于两者之间的解决方案(关于复杂性)可能是:

CompletionStage<Combined> combinedDataCompletionStage = aCompletionStage.thenCompose(
    a -> bCompletionStage.thenCompose(b -> cCompletionStage.thenCompose(
        c -> dCompletionStage.thenApply(d -> combine(a, b, c, d)))));

这在其结构上更简单,但随着更多阶段的出现,仍然不能很好地扩展。


答案 2

霍尔格的第三个答案可以缩短一点:

CompletionStage<Combined> combinedDataCompletionStage = aCompletionStage.thenCompose(
    a -> bCompletionStage.thenCompose(
        b -> cCompletionStage.thenCombine(dCompletionStage,
            (c, d) -> combine(a, b, c, d))));

推荐