2017-01-24 11 views
1

私にはExecutorServiceがあり、これにはn Callableを提出しています。これらのそれぞれにおいて、Callablesの場合、私は新しいCallableを生成し、それは同じExecutorServiceに提出されます。 Future.get()の最初のn Callableのいずれかにjava.util.concurrent.TimeoutExceptionが出現した場合、にはFuture.cancel(true)があります。また、私が提出したタスクは、キャンセルされたCallableのためキャンセルする必要があります。Future.cancelの後に生まれたCallableを取り消すにはどうすればいいですか?

これを行う方法の1つは、呼び出されたCallableをコールスタックのどこかのリストのマップに保存し、Callableをキャンセルして子を見つけてキャンセルすることです。しかし、これは私にとって非常に良い解決策ではないようです。キャンセルの論理はどこか近くにあるべきです。

この柔軟性を与えるハンドラ/より良い方法がありますか?

+1

:よう

何か。したがって、キャンセルのために_interrupt_を受け取ると、その "子"に対して "cancel"を呼び出す必要があります。 –

+0

callableaを持っていることに気をつけて、同じプール上の自分の呼び出し可能コードをブロックしてください。それはデッドロックのレシピです。 –

+0

@SotiriosDelimanolisあなたが私のルートの中にtry catchブロックを持っていると言うことを意味しますか?クリーンアップを行うためにThreadInterruptedExceptionを検出するためにCallableを呼び出しますか? Future.cancel()はこの例外のトリガーを確実にしますか? – zafar142003

答えて

2

それぞれのFuture.get()で最初のn Callableのいずれかでjava.util.concurrent.TimeoutExceptionが発生した場合、そのCallableでFuture.cancel()を実行します。私はまた、キャンセルされたCallableのために提出したタスクをキャンセルする必要があります。

future.cancel(false)に電話すると、ジョブがまだ実行されていない場合にのみ実行されます。この場合、「サブジョブ」は作成されていないため、問題はありません。

だから私はジョブが既に実行されている場合、スレッドを中断するfuture.cancel(true)について話していると仮定します。この中断がだけがInterruptedException - Thread.sleep(...),obj.wait(...)などのようないくつかのメソッドに影響することに気づくことが重要です。そうでない場合は、コード内の割り込みフラグをテストする必要があります。例えば:私はどうなるのか

while (!Thread.currentThread().isInterrupted()) { 
    ... 
} 

は、あなたの仕事のそれぞれが、ちょうどそれが生み出したことFuture S「サブジョブ」のリストを維持することです。 InterruptedExceptionが検出されたとき、またはスレッド割り込みフラグが設定されていることが通知されたときには、分岐したすべてのジョブに対してfuture.cancel(true)を呼び出すことができます。これは、ルート `Callable`は、その生成された` Callable`sを調整する必要があるように思える

final List<Future<...>> subJobs = new ArrayList<>(); 
... 
while (true) { 
    if (Thread.currentThread().isInterrupted()) { 
     cleanupSubJobs(subJobs); 
     break; 
    } 
    try { 
     Thread.sleep(...); 
    } catch (InterruptedException ie) { 
     // always a good pattern 
     Thread.currentThread.interrupt(); 
     cleanupSubJobs(subJobs); 
     return; 
    } 
    ... 
    if (weNeedSubJob) { 
     subJobs.add(threadPool.submit(...)); 
    } 
} 
... 
private void cleanupSubJobs(List<Future<...>> subJobs) { 
    for (Future<...> subJob : subJobs) { 
     subJob.cancel(true); 
    } 
} 
+0

答えをありがとう。私の第2レベルのCallableの中に無限のwhileループを導入する簡単な方法はないようです。基本的には、サブジョブをスレッドプールにサブミットし、サブジョブが戻るのを待ちます。しかし、Future.get()はInterruptedExceptionをスローすることがわかります。 Callableの第2レベルでそれを捉えれば、そこにあるすべてのサブタスクを取り消すことができます。 – zafar142003

+0

それはちょうど@ zafar142003と聞こえます。 – Gray

関連する問題