Callable タスクのコレクションを受け取り、それらを並行して実行する単純なユーティリティを作成しています。所要時間の合計が、最長のタスクにかかる時間よりも少ないことを期待します。このユーティリティは、いくつかのエラー処理ロジックも追加します。いずれかのタスクが失敗し、その失敗が「再試行可能」として処理できるもの (タイムアウトやユーザー指定の例外など) である場合、タスクを直接実行します。
このユーティリティを ExecutorService に実装しました。次の 2 つの部分があります。
- submit() すべての Callable タスクを ExecutorService に送信し、Future オブジェクトを格納します。
- for ループで、各 Future の結果を get() します。例外が発生した場合は、「再試行可能な」ロジックを実行します。
このユーティリティを使用すると、タスクを順番に実行するよりも高速であることを確認するために、いくつかの単体テストを作成しました。テストごとに、特定の数の Callable を生成し、それぞれが基本的に Thread.sleep() を境界内のランダムな時間実行します。さまざまなタイムアウト、さまざまな数のタスクなどを試してみたところ、ユーティリティは順次実行よりも優れているように見えました。
しかし、この種のユーティリティを必要とする実際のシステムにそれを追加したところ、結果は非常に変わりやすいものでした。並列実行が高速な場合もあれば、低速な場合もあり、高速な場合もありましたが、それでも、最長の個人タスク.
私はそれをすべて間違っているだけですか?ExecutorService に invokeAll() があることは知っていますが、それは基になる例外を飲み込みます。また、CompletionService を使用して、完了した順序でタスクの結果をフェッチしようとしましたが、多かれ少なかれ同じ動作を示しました。私は今、ラッチとバリアについて調べています。これは、この問題を解決するための正しい方向ですか?