2016-08-31 14 views
1

「ブール(ブールmayInterruptIfRunning)をキャンセルこのタスクの 実行の取り消しを試みます。タスクはすでに が完了している場合、この試みは失敗します、すでにキャンセルされた、または 他の何らかの理由でキャンセルすることができませんでした」上記の理由のほかにタスクのキャンセルに失敗した原因は何ですか?

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

、それはタスクをキャンセルするために失敗する他の理由は何でしょうか。 また、タスクが以下のようなコードを実行してもキャンセルできますか?

+0

は、任意の数の理由があるかもしれませんが、彼らはすべてのカテゴリ」の下に下落するだろう:中断に応答メソッドを呼び出す

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

も働くだろうあなたのキャンセル要求にもかかわらずタスクは停止しません "。あなたの真のループは、それらの多くの理由の一つでしょう。 –

+0

@アーウィン、それらのためのルール\パターンはありますか? – Jason

+0

どのタイプのタスクをキャンセルすることができますか、どのパターン? – Jason

答えて

2

投稿したwhileループは、中断に応答するものがないため、キャンセルできないコードの例になります。

ソケットリッスンをブロックするコードでも、割り込みを処理できない可能性があります。 InterruptedIOExceptionでコードがタイムアウトしても、割り込みフラグを設定せずに例外をスワップすると、コードは割り込みを処理できません。

だからTLDR:1)IOをブロックするコード 2)中断の仕方を知らないコード。または両方の組み合わせ。

0

実際にJavaでスレッドを終了させる良い方法はありません。基本的にはスレッドに停止を指示することはできますが、スレッドは常に待機していてフラグやそれに類する問題を読み取ることはできません。実際には複雑な問題です。だから私は、彼らは単に "いくつかの問題"のために言ったことを前提としています。

+0

そこにはどのようなルール\パターンがありますか?どのタイプのタスクを取り消すことができますか? – Jason

+0

推奨される方法は、スレッド内のフラグを定期的にチェックすることです。それは本当にあなたが実際にどのように仕事をするかまでです。これは明らかに、スレッドが永遠に、または長時間実行される場合にのみ発生します。他のケースでは、そのスレッドを実行させ、処理した後に処理するほうがよいでしょう。コンテキストが壊れても、スレッドから戻ったばかりの典型的なケース。 – breakline

0

各スレッドには、割り込み状態を保持する特別なフラグがあり、isInterrupted()メソッドでアクセスできます。誰かがスレッドを中断すると、このフラグはtrueに設定されます。それで全部です。このスレッドによって実行されるコードがこのフラグをチェックしてInterruptedExceptionをスローするか、可能であればスレッドの実行を終了するまで、実際の割り込みは発生しません。

現在のスレッドをブロックするように設計された標準ライブラリの多くのメソッドは、実際にはこのフラグを時々チェックし、フラグが設定されているとInterruptedExceptionをスローします。例えば、Thread.sleep(),Thread.join(),Object.wait(),Lock.lockInterruptibly()など多くのものがある。したがって、あなたのスレッドが定期的にこのフラグを明示的にチェックしたり暗黙的にチェックする記述されたメソッドのいくつかによってブロックされたりすると、そのスレッドは中断します。そうでなければ、そうではありません。

したがって、ループが空のスレッドは、中断状態をチェックしないため中断できません。しかし、中断状態のチェックを追加すると、それを修正します:

try { 
    while (true) { 
     Thread.sleep(timeout); 
    } 
} catch(InterruptedException e) { 
    // Do nothing, just let the thread exit 
} 
関連する問題