2

次のテスト コードを使用して InterruptedException をテストしています。

Runnable runMe = new Runnable() {
    @Override
    public void run() {
        for(int i=0; i<6; i++) {
            System.out.println("i = "+i);
            if(i==3) {
                System.out.println("i==3, Thread = " 
                +Thread.currentThread().getId());
                //I invoke interrupt() on the working thread.
                Thread.currentThread().interrupt();
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    //I caught InterruptedException
                    System.out.println(Thread.currentThread().getId() 
                    + " is interrupted!");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }   
};          
Thread workingThread = new Thread(runMe);
workingThread.start();
try {
    workingThread.join();
} catch (InterruptedException e) {
    //Swallow
}
//the following log shows me workingThread.isInterrupted() is false, why?
System.out.println("workingThread(" 
+ workingThread.getId()+") interrupted ? " 
+ workingThread.isInterrupted());

ではrun()interrupt()現在作業中のスレッドで、InterruptedException.

メインスレッドでは、コードの最後の行はSystem.out.println(...)、作業スレッドの割り込みステータスを出力するものです。に引っかかっInterruptedExceptionたので、 trueというメッセージがrun()表示されるはずなのに、false になったのはなぜですか?workingThread.isInterrupted()

4

2 に答える 2

4

Oracle のJava 同時実行チュートリアルには次のように書かれています (私の強調が追加されています)。

割り込みステータス フラグ

割り込みメカニズムは、割り込みステータスと呼ばれる内部フラグを使用して実装されます。Thread.interrupt を呼び出すと、このフラグが設定されます。スレッドが静的メソッド Thread.interrupted を呼び出して割り込みをチェックすると、割り込みステータスがクリアされます。あるスレッドが別のスレッドの割り込みステータスを照会するために使用する非静的 isInterrupted メソッドは、割り込みステータス フラグを変更しません。

慣例により、InterruptedException をスローして終了するメソッドは、その時点で割り込みステータスをクリアします。ただし、割り込みを呼び出す別のスレッドによって、割り込みステータスがすぐに再度設定される可能性は常にあります。

あなたが見ているのは、スレッドが中断され、終了するメソッドが結合であることです(実際には、結合は Object.wait を呼び出すことによって実装されるため、スタックトレースは、待機が例外がスローされたメソッドであることを示すと思います)、チュートリアルにあるように、フラグはクリアされます。

スレッドの割り込みステータスフラグを再度設定する必要があるかどうかを決定するのは、例外のハンドラー次第です。ハンドラーが別のことを行うようにコーディングされていない限り、デフォルトの想定では、例外が処理され、フラグを設定する必要はもうありません。

Thread#interruptのAPI ドキュメントは、これと一致しています。

このスレッドが Object クラスの wait()、wait(long)、または wait(long, int) メソッド、または join()、join(long)、join(long, int) の呼び出しでブロックされている場合、sleep(long)、または sleep(long, int)、このクラスのメソッドの場合、その割り込みステータスはクリアされ、InterruptedException を受け取ります。

ここで、中断がこのように設計された理由について詳しく説明した答えがあります。

于 2014-10-17T17:20:07.167 に答える