あなたは、次のヘルパーメソッドを使用ことがあります
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());
この解決策の1つの欠点は、はありません。が完了した場合、すべて未完了であることです。成功した計算がある場合、最初の値を提供しますが、まったく成功した計算が存在しない場合、非常に失敗するソリューションは、もう少し複雑です:
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
年代その並外れハンドラ事実を利用しますすべての先物が完了した(例外的にまたはそうでない)と、将来が1回だけ完了できる(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()); }
の例では、上記のソリューションは、すべての補完のためにお待ちしておりますことを実証遅延を使用しています成功していない場合はthis example on ideoneと表示されます。結果のアイデアキャッシングにより、遅延に気付かないことがあります。
すべての先物が失敗した場合、どの例外が報告されるかについての保証はないことに注意してください。誤ったケースではすべての補完を待つので、最終的な結果にすることができます。それを考えると
私たち[チャットでこのディスカッションを続行](http://chat.stackoverflow.com/rooms/97948/discussion-between-basilevs-and-holger)。 – Basilevs
@Basilevs:回答を拡大しました – Holger