Threadでのinterruptの使い方
合理的な割り込みスレッド
合理的な中断
以上の理由により、Javaは新しい割り込みメカニズム(interrupt)を提供し、他のスレッドはスレッドを終了したいスレッドがブロック状態(sleep,wait,join)の場合、スレッドが放出される スレッドが正常に動作している場合は正常に動作するが、中断したフラグはtrueに設定されており、自分の終了を通知されたことに相当する. 呼び出されたスレッドがブロックされています
呼び出されたスレッドは正常に動作しています
呼び出すスレッドがブロックされていない場合は、フラグを監視するためのメソッドを呼び出す必要がある.
このプログラムはinterruptフラグを検出する、interruptフラグがtrueに設定されていることを発見すると、自分自身を終了する.
interrupted()とisInterrupt()の違い
違い:interruptフラグをクリアするかどうか.isInterrupt()メソッドはフラグを変更しないが、interrupted()メソッドは検出と同時にフラグがtrueであることが判明するとtrueを返し、フラグをfalseに設定.
前述の例では、Thread.interrupted()メソッドは、trueとしてマークする場合にinterruptedのフラグを変更する.
ソース解析
ソースコードを観察することにより、interruptedメソッドは最後にisInterrupted(true)メソッドを呼び出し、入力パラメータはフラグビットをクリアするかどうかを表す.isInterrupted(boolean)はローカルメソッドであり、最終的にはC/C++で実行される.isInterrupted()が最後に入力パラメータはfalseであり、フラグビットをクリアしないことを示す.
合理的な中断
Thread
クラスでは、stop()
、suspend()
およびresume()
メソッドが提供されています.この3つのメソッドは、それぞれ終了、一時停止、スレッドの復元に使用されます.しかし、@Deprescatedとマークされて廃棄されています.1つのスレッドは他のスレッドで終了するべきではありません.彼は他の人の通知を受け取るべきで、それから自分が適切な位置で終了し、不合理な終了であれば、臨界領域がまだ完全に操作されていない、ロックを早期に解除しているが、一部の状態が変化している、クリーンアップ操作が行われていないなど、多くの意外な結果をもたらす.以上の理由により、Javaは新しい割り込みメカニズム(interrupt)を提供し、他のスレッドはスレッドを終了したい
interrupt()
メソッドを呼び出します.このとき、スレッドは自分の状態に応じて応答します.InterruptedException
異常public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
try {
// 30s
sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
try {
//
thread.start();
// 3
TimeUnit.SECONDS.sleep(3);
//
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// ↓ out ↓
// java.lang.InterruptedException: sleep interrupted
// ...
呼び出されたスレッドは正常に動作しています
呼び出すスレッドがブロックされていない場合は、フラグを監視するためのメソッドを呼び出す必要がある.
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println(" ...");
}
}
};
try {
thread.start();
TimeUnit.SECONDS.sleep(3);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// ↓ out ↓
//
// ...
このプログラムはinterruptフラグを検出する、interruptフラグがtrueに設定されていることを発見すると、自分自身を終了する.
interrupted()とisInterrupt()の違い
違い:interruptフラグをクリアするかどうか.isInterrupt()メソッドはフラグを変更しないが、interrupted()メソッドは検出と同時にフラグがtrueであることが判明するとtrueを返し、フラグをfalseに設定.
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println(" ...");
}
// ⚠️⚠️ ⚠️⚠️
System.out.println(Thread.interrupted());
}
};
try {
thread.start();
TimeUnit.SECONDS.sleep(3);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// ↓ out ↓
// ...
// ...( )
// false
前述の例では、Thread.interrupted()メソッドは、trueとしてマークする場合にinterruptedのフラグを変更する.
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
// ⚠️⚠️ ⚠️⚠️
while (!isInterrupted()) {
System.out.println(" ...");
}
System.out.println(Thread.interrupted());
}
};
try {
thread.start();
TimeUnit.SECONDS.sleep(3);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// ↓ out ↓
// ...
// ...( )
// true
ソース解析
ソースコードを観察することにより、interruptedメソッドは最後にisInterrupted(true)メソッドを呼び出し、入力パラメータはフラグビットをクリアするかどうかを表す.isInterrupted(boolean)はローカルメソッドであり、最終的にはC/C++で実行される.isInterrupted()が最後に入力パラメータはfalseであり、フラグビットをクリアしないことを示す.