6

長時間実行されるマルチスレッド処理を行うために、リストを使用Executors.newCachedThreadPool()しています。メインスレッドは、すべてのスレッドが終了するまでブロックされ、によって返された先物を処理できます。ただし、の1つが例外をスローし、他のスレッドを終了した場合は、すぐに戻りたいと思います。invokeAllCallableinvokeAllinvokeAllCallable

executeの代わりに使用すると、実行をスローするものである必要はないinvokeAll最初のブロックがブロックされます。future.get()

ビジーウェイトを使用してすべての先物をループし、チェックisDone()することも最善の方法ではないようです。

4

1 に答える 1

7

ラッチ、バリア、セマフォなどのより複雑な同期メカニズムを使用できますが、を参照してくださいExecutorCompletionService。これは軽量のラッパーであり、最初に完了したタスクExecutorServiceをリッスンできます。簡単な例を次に示します。

final ExecutorService executorService = Executors.newCachedThreadPool();
final ExecutorCompletionService<String> completionService = 
            new ExecutorCompletionService<String>(executorService);
for (int i = 0; i < 10; ++i) {
    completionService.submit(new Task());
}
completionService.take().get();

コードは非常に単純です。まず、でラップexecutorServicecompletionServiceます。後でそれを使用して、タスクを次々に送信します。最後の行は非常に重要です。終了した最初のタスクを取得し、結果を取得しようとします。例外がスローされた場合は、ここで再スローされ、次のようにラップされExecutionExceptionます。

try {
    completionService.take().get();
} catch (ExecutionException e) {
    e.getCause();       //this was thrown from task!
}

ブロック内catchでは、残りのタスクをキャンセルしたり、スレッドプール全体をシャットダウンしたりするなど、なんらかの方法で例外を処理できます。

もちろん、take()10回呼び出すことで、すべてのタスクが完了するのを自由に待つことができます。少なくとも1つのタスクが終了している限り、各呼び出しはブロックされます。

于 2013-01-10T18:48:55.773 に答える