InterruptedException はあなたが思っているほど単純ではないかもしれません。
Java オブジェクトの wait() メソッドまたはスレッドの sleep() メソッドを呼び出すときは、InterruptedException 例外をキャッチして処理する必要があります。 InterruptedException を不適切に処理すると、予期しない結果が発生します。
たとえば、次のプログラム コードでは、InterruptedTask クラスは Runnable インターフェイスを実装しています。run() メソッドで現在のスレッドのハンドルが取得され、 while(true) ループ、 isInterrupted() メソッドを使用して、現在のスレッドが中断されているかどうかを検出します。現在のスレッドが中断された場合は、while(true) ループを終了します。同時に、while(true) ループでは、これは Thread.sleep(100) コードの行でもあり、InterruptedException 例外をキャプチャします。
コード全体は次のとおりです。
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 线程测试中断 */ public class InterruptedTask implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
上記のコードの本来の目的は、isInterrupted() メソッドによってスレッドが中断されたかどうかを確認し、中断された場合は while ループを終了することです。他のスレッドは、実行スレッドのinterrupt()メソッドを呼び出すことで実行スレッドに割り込みますが、このとき、実行スレッドの割り込みフラグビットがセットされるため、currentThread.isInterrupted()がtrueを返し、whileループを実行することができます。出ました。
これは問題ないようです。 しかし、これは本当にそうなのでしょうか? テスト用に InterruptedTest クラスを作成します。コードは次のとおりです。
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 测试线程中断 */ public class InterruptedTest { public static void main(String[] args){ InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } interruptedThread.interrupt(); } }
以下に示すように main メソッドを実行します。
上記のコードは明らかにスレッドの中断() メソッドを呼び出してスレッドを中断していますが、効果はありません。その理由は、スレッドの run() メソッドが実行されると、ほとんどの場合、sleep(100) でブロックされ、他のスレッドが実行スレッドの中断() メソッドを呼び出して実行スレッドに割り込むと、InterruptedException が発生します。例外として、InterruptedException 例外がトリガーされると、JVM はスレッドの割り込みフラグ ビットを同時にクリアします。そのため、このとき run() メソッドで currentThread.isInterrupted() が判断されます。 false を返し、現在の while ループは終了しません。
問題分析が完了したので、スレッドを中断してプログラムを終了するにはどうすればよいですか?
これを処理する正しい方法は、InterruptedTas の run() メソッドの while(true) ループで例外をキャッチした後で行う必要がありますk class 割り込みフラグ ビットをリセットするため、InterruptedTask クラスの正しいコードは次のようになります。
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 中断线程测试 */ public class InterruptedTask implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); currentThread.interrupt(); } } } }
ご覧のとおり、InterruptedException 例外をキャプチャする新しいコード行を catch コード ブロックに追加しました。
currentThread.interrupt();
これにより、InterruptedException 例外をキャッチした後、スレッドの割り込みフラグ ビットをリセットして、現在実行中のスレッドを中断することができます。
次に示すように、InterruptedTest クラスの main メソッドを再度実行します。
InterruptedException の処理には注意してください。実行スレッドの中断() メソッドを呼び出して実行スレッドを中断するときに、InterruptedException がスローされた場合、 InterruptedException 例外が発生すると、JVM は実行スレッドの割り込みフラグビットを同時にクリアしますが、このとき実行スレッドの isInterrupted() メソッドを呼び出すと false が返されます。
現時点で、これを処理する正しい方法は、実行スレッドの run() メソッドで InterruptedException 例外をキャプチャし、割り込みフラグ ビット (つまり、 InterruptedException 例外が発生した場合は、現在のスレッドの中断() メソッドを再度呼び出します)。
以上がJava での同時実行性の高い InterruptedException の問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。