您可以使用以下帮助程序方法:
public static <T>
CompletableFuture<T> anyOf(List<? extends CompletionStage<? extends T>> l) {
CompletableFuture<T> f=new CompletableFuture<>();
Consumer<T> complete=f::complete;
l.forEach(s -> s.thenAccept(complete));
return f;
}
您可以像这样使用它来证明它将忽略前面的异常,但返回第一个提供的值:
List<CompletableFuture<String>> futures = Arrays.asList(
CompletableFuture.supplyAsync(
() -> { throw new RuntimeException("failing immediately"); }
),
CompletableFuture.supplyAsync(
() -> { LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
return "with 5s delay";
}),
CompletableFuture.supplyAsync(
() -> { LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(10));
return "with 10s delay";
})
);
CompletableFuture<String> c = anyOf(futures);
logger.info(c.join());
这种解决方案的一个缺点是,如果所有期货都异常完成,它将永远不会完成。一个解决方案,如果计算成功,将提供第一个值,但如果根本没有成功的计算,则会异常失败,这涉及得更多:
public static <T>
CompletableFuture<T> anyOf(List<? extends CompletionStage<? extends T>> l) {
CompletableFuture<T> f=new CompletableFuture<>();
Consumer<T> complete=f::complete;
CompletableFuture.allOf(
l.stream().map(s -> s.thenAccept(complete)).toArray(CompletableFuture<?>[]::new)
).exceptionally(ex -> { f.completeExceptionally(ex); return null; });
return f;
}
它利用了这样一个事实,即 只有在所有期货完成(特殊或非)之后才会调用异常处理程序,并且未来只能完成一次(让特殊的事情放在一边)。当执行异常处理程序时,任何完成带有结果的未来(如果有)的尝试都已完成,因此,如果以前没有成功完成,则异常完成它的尝试只会成功。allOf
obtrude…
它可以以与第一个解决方案完全相同的方式使用,并且只有在所有计算失败时才表现出不同的行为,例如:
List<CompletableFuture<String>> futures = Arrays.asList(
CompletableFuture.supplyAsync(
() -> { throw new RuntimeException("failing immediately"); }
),
CompletableFuture.supplyAsync(
// delayed to demonstrate that the solution will wait for all completions
// to ensure it doesn't miss a possible successful computation
() -> { LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
throw new RuntimeException("failing later"); }
)
);
CompletableFuture<String> c = anyOf(futures);
try { logger.info(c.join()); }
catch(CompletionException ex) { logger.severe(ex.toString()); }
上面的示例使用延迟来演示解决方案将在没有成功时等待所有完成,而 ideone 上的此示例将演示以后的成功将如何将结果变为成功。请注意,由于结果的 Ideones 缓存,您可能不会注意到延迟。
请注意,如果所有期货都失败,则无法保证报告哪些异常。由于它会等待错误情况下的所有完成,因此任何结果都可能达到最终结果。