How to implement CompletableFuture.allOf() that completes exceptionally once any of the futures fail?

后端 未结 2 1216
暖寄归人
暖寄归人 2020-12-11 12:57

I want to implement a hybrid of CompletableFuture.allOf() and CompletableFuture.anyOf() where the returned future completes successfully as soon as

相关标签:
2条回答
  • 2020-12-11 13:28

    This question is actually very similar to Replace Futures.successfulAsList with Java 8 CompletableFuture?

    Although the question is not exactly the same, the same answer (from myself) should satisfy your needs.

    You can implement this with a combination of allOf() and chaining each input future with an exceptionally() that would make the future returned by allOf() immediately fail:

    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;
        }));
    
    0 讨论(0)
  • 2020-12-11 13:29

    I believe this will do the job:

    /**
     * @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));
    }
    
    0 讨论(0)
提交回复
热议问题