2013-01-10 9 views
5

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

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

すべての先物をループし、isDone()をチェックするためにビジー状態の待機を使用することは、最善の方法ではないようです。

+0

あなたはexecutosサービスをシャットダウンして、他のタスクを中断してみましたか?これらの他のタスクが待機/読んでいない場合は、スレッドの中断フラグを毎時確認してから – radai

答えて

6

ラッチ、バリア、またはセマフォなどのより複雑な同期メカニズムを使用できますが、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でラップされます。catchブロック内の

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

あなたが何らかの形で、例えば、例外を処理することができます残りのタスクを取り消したり、スレッドプール全体をシャットダウンしたりします。

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

+0

+1これで勝てます;-) – assylias

+0

例外の際に残りのスレッドをどのように終了させますか? –

+0

@ zaske:それぞれ 'submit()'は 'Future 'を返します。例外が発生した場合は、すべての未来を繰り返し、キャンセル()してください。 –

関連する問題