如何实现CompletableFuture.allOf(),一旦任何期货失败,它就会异常完成?

时间:2018-07-31 20:23:45

标签: java completable-future

我想实现CompletableFuture.allOf()CompletableFuture.anyOf()的混合体,其中返回的未来将在所有元素成功完成后立即成功完成,或者在异常情况下尽快完成(相同例外)任何要素都异常完善。如果有多个元素失败,则返回任何一个元素的异常就足够了。

用例

我有一个任务需要汇总CompletableFuture列表返回的子结果,但是只要其中任何一个失败,该任务就应该停止等待。我知道子任务将继续运行,没关系。

相关问题

我发现Waiting on a list of Future最初看起来像是一个重复的问题,但接受的答案使用CompletionService,它需要输入CallableRunnable。我正在寻找一种将已经运行的CompletionStage作为输入的解决方案。

2 个答案:

答案 0 :(得分:1)

这个问题实际上与Replace Futures.successfulAsList with Java 8 CompletableFuture?

非常相似

尽管问题并不完全相同,但相同的答案(来自我自己)应该可以满足您的需求。

您可以结合使用allOf()并将其与exceptionally()链接在一起,从而使allOf()返回的未来立即失败:

CompletableFuture<String> a = …, b = …, c = …;
CompletableFuture<Void> allWithFailFast = CompletableFuture.allOf(a, b, c);
Stream.of(a, b, c)
    .forEach(f -> f.exceptionally(e -> {
        allWithFailFast.completeExceptionally(e);
        return null;
    }));

答案 1 :(得分:-1)

我相信这可以完成工作:

/**
 * @param arrayOfFutures an array of futures to wait on
 * @return a {@code CompletableFuture} that completes successfully once all elements have completed successfully, or completes
 * exceptionally after any of the elements has done the same
 * <br>{@code @throws NullPointerException} if {@code arrayOfFutures} is null
 */
public CompletableFuture<Void> waitForAllButAbortOnFirstException(CompletableFuture<?>... arrayOfFutures)
{
    if (arrayOfFutures == null)
      return CompletableFuture.failedFuture(new NullPointerException("arrayOfFutures may not be null"));
    if (arrayOfFutures.length == 0)
        return CompletableFuture.completedFuture(null);
    return CompletableFuture.anyOf(arrayOfFutures).
        thenApply(unused ->
        {
            // Remove any futures that completed normally and try again
            return Arrays.stream(arrayOfFutures).
                filter(element -> !element.isDone() || element.isCompletedExceptionally()).
                toArray(CompletableFuture[]::new);
        }).
        thenCompose(remainingFutures -> waitForAllButAbortOnFirstException(remainingFutures));
}