2012-05-01 13 views
16

最近スレッドセーフをほとんど備えていない大きなJavaアプリケーションを継承しました。私が現在取り組んでいるのは、非常に悪いThread.stop()を使用する代わりに、すべてのスレッドが正しく処理されるようにすることです。Thread.interrupt()フラグをクリアするメソッド

一部の問題は、割り込みフラグをクリアするすべてのメソッドを呼び出すことがわからないことがあります。私は他に何が足りないのです

Thread.interrupted() 
Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Object.wait() 
Object.wait(long) 

現在、私は次の割り込みフラグをクリアすることを知っていますか?ありがとう

答えて

25

問題の一部は、割り込みフラグをクリアするすべてのメソッド呼び出しがわからないということでした。

以下の方法がちょうどそれらを呼び出すことにより、割り込みフラグをクリアすることを明らかにすることが重要である。このような理由のためにThread.currentThread().isInterrupted()

Thread.interrupted() 
Thread.isInterrupted(true) -- added to your list 

は常に代わりに使用する必要があります。

以下の方法がInterruptedExceptionをスロー直ちににより中断フラグをクリアするか(以下のJUnitコードを参照して、それらが呼び出され、スレッドがが既にが中断された場合、スレッドは、又はを中断した後、それらが呼び出された場合)。したがって、フラグをクリアするメソッドではなく、例外をスローします。

Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Thread.join(int, long) – added to your list 
Object.wait() 
Object.wait(long) 
Object.wait(int, long) – added to your list 
BlockingQueue.put(...) – added to your list 
BlockingQueue.offer(...) – added to your list 
BlockingQueue.take(...) – added to your list 
BlockingQueue.poll(...) – added to your list 
Future.get(...) – added to your list 

に注意してくださいそのすぐにスレッドを再中断することであるInterruptedExceptionをキャッチ任意のコードとの適切なパターン。これのいくつかを示してい

try { 
    ... 
} catch (InterruptedException e) { 
    // immediately re-interrupt the thread 
    Thread.currentThread().interrupt(); 
    // log the exception or [likely] quit the thread 
} 

のJUnitコード:

assertFalse(Thread.currentThread().isInterrupted()); 
// you can do this from another thread by saying: someThread.interrupt(); 
Thread.currentThread().interrupt(); 
// this method does _not_ clear the interrupt flag 
assertTrue(Thread.currentThread().isInterrupted()); 
// but this one _does_ and should probably not be used 
assertTrue(Thread.interrupted()); 
assertFalse(Thread.currentThread().isInterrupted()); 
Thread.currentThread().interrupt(); 
assertTrue(Thread.currentThread().isInterrupted()); 
try { 
    // this throws immediately because the thread is _already_ interrupted 
    Thread.sleep(1); 
    fail("will never get here"); 
} catch (InterruptedException e) { 
    // and when the InterruptedException is throw, it clears the interrupt 
    assertFalse(Thread.currentThread().isInterrupted()); 
    // we should re-interrupt the thread so other code can use interrupt status 
    Thread.currentThread().interrupt(); 
} 
assertTrue(Thread.currentThread().isInterrupted()); 
10

一般的な規則は次のとおりです。InterruptedException(+ Thread.interrupted())をスローするメソッドは、割り込みフラグをクリアします。

スレッドを中断させるには、InterruptedExceptionがキャッチされた場所をすべて見つけ出し、再試行したり割り込みフラグを復元したりする必要がありません。 InterruptedExceptionはチェックされた例外であるため、実行するのは難しくありません。

+0

これは、私が実行したコードベースで最初のパスが投げられたのですが、前のプログラマーがInterruptedExceptionの代わりに一般的なExceptionをキャッチする状況に直面しています。 – OverflowingStack

1

ここSUPER FUN例です:

ch.qos.logback私たちは、ケースの他にこれを行うにはthread.isInterrupted()方法に依存していますバージョン1.1.4より前の.core.AsyncAppenderBaseは、スレッドのフラグをリセットせずにInterruptedExceptionをキャッチして取り込みます。

したがって、このロガーにルーティングするもの(slf4jなど)を使用すると、スレッドの割り込みステータスが静かに低下します。 'Cos、つまり、スレッドの中断状況をすべてのログ操作の前後でチェックしないのは誰ですか?

関連する問題