実行中の非同期タスクはほとんどなく、そのうちの少なくとも 1 つが終了するまで待つ必要があります (将来的には、N 個のタスクのうち util M 個が終了するのを待つ必要があるでしょう)。現在、それらはFutureとして提示されているため、次のようなものが必要です
/**
* Blocks current thread until one of specified futures is done and returns it.
*/
public static <T> Future<T> waitForAny(Collection<Future<T>> futures)
throws AllFuturesFailedException
このようなことはありますか?または同様のもの、Future には必要ありません。現在、先物のコレクションをループし、1 つが終了したかどうかを確認してから、しばらくスリープしてからもう一度確認します。これは最善の解決策ではないように見えます。長時間スリープすると不要な遅延が追加され、短時間スリープするとパフォーマンスに影響する可能性があるためです。
使ってみることができました
new CountDownLatch(1)
タスクが完了するとカウントダウンを減らして実行します
countdown.await()
、しかし、未来の創造を制御する場合にのみ可能であることがわかりました。可能ですが、システムの再設計が必要です。現在、タスク作成のロジック (Callable を ExecutorService に送信する) は、どの Future を待つかの決定から分離されているためです。オーバーライドすることもできました
<T> RunnableFuture<T> AbstractExecutorService.newTaskFor(Callable<T> callable)
RunnableFuture のカスタム実装を作成し、タスクが終了したときに通知されるようにリスナーをアタッチし、そのようなリスナーを必要なタスクにアタッチして CountDownLatch を使用しますが、これは、使用する ExecutorService ごとに newTaskFor をオーバーライドする必要があることを意味します。 AbstractExecutorService を拡張しません。同じ目的で指定された ExecutorService をラップすることもできますが、Future を生成するすべてのメソッドをデコレートする必要があります。
これらの解決策はすべてうまくいくかもしれませんが、非常に不自然に見えます。次のような単純なものが欠けているようです
WaitHandle.WaitAny(WaitHandle[] waitHandles)
C#で。この種の問題に対するよく知られた解決策はありますか?
アップデート:
もともと私は Future の作成にまったくアクセスできなかったので、エレガントな解決策はありませんでした。システムを再設計した後、Future の作成にアクセスし、実行プロセスに countDownLatch.countdown() を追加できたので、countDownLatch.await() を実行すると、すべて正常に動作します。他の回答に感謝します。私は ExecutorCompletionService について知りませんでした。実際に同様のタスクで役立つ可能性がありますが、この特定のケースでは、一部の Future がエグゼキューターなしで作成されるため、使用できませんでした。実際のタスクはネットワーク経由で別のサーバーに送信されます。リモートで完了し、完了通知を受け取ります。