我想实现CompletableFuture.allOf()
和CompletableFuture.anyOf()
的混合体,其中返回的未来将在所有元素成功完成后立即成功完成,或者在异常情况下尽快完成(相同例外)任何要素都异常完善。如果有多个元素失败,则返回任何一个元素的异常就足够了。
我有一个任务需要汇总CompletableFuture
列表返回的子结果,但是只要其中任何一个失败,该任务就应该停止等待。我知道子任务将继续运行,没关系。
我发现Waiting on a list of Future最初看起来像是一个重复的问题,但接受的答案使用CompletionService
,它需要输入Callable
或Runnable
。我正在寻找一种将已经运行的CompletionStage
作为输入的解决方案。
答案 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));
}