JAVA線程-interrupt
中斷一個線程非常簡單,只需要在其他線程中對目標線程調用interrupt()
方法,目標線程需要反覆檢測自身狀態是否是interrupted狀態,如果是,就立刻結束運行。
案例一:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(1); // 暫停1毫秒
t.interrupt(); // 中斷t線程
t.join(); // 等待t線程結束
System.out.println("end");
}
}
class MyThread extends Thread {
public void run() {
int n = 0;
while (! isInterrupted()) {
n ++;
System.out.println(n + " hello!");
}
}
}
Output:
....
33 hello!
34 hello!
35 hello!
end
上述案例很簡單,就是調用mythread的interrupt()方法,MyThread內部run中對線程中的中斷狀態進行判斷,並沒有真正意義上中斷線程。
案例二:
public class ThreadInterruptTest {
public static void main(String[] args) {
try {
Thread t = new MyThread();
t.start();
Thread.sleep(1); // 暫停1毫秒
System.out.println("before invoke interrupted");
t.interrupt(); // 中斷t線程
System.out.println("before main join");
t.join(); // 等待t線程結束
System.out.println("end");
} catch (InterruptedException e) {
System.out.println("main interrupted!");
}
}
}
class MyThread extends Thread {
public void run() {
int n = 0;
try {
while (!isInterrupted()) {
n++;
System.out.println(n + " hello!");
}
// mythread如果被調用了interrupt方法,並且mythread線程run方法中有拋出InterrutpedException的方法,就會拋出,沒有就不會拋出
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("mythread interrupted");
}
}
}
Output:
1 hello!
.....
51 hello!
before invoke interrupted
before main join
52 hello!
mythread interrupted
end
該案例就是案例一中,對MyThread中run方法新增了Thread.sleep方法調用,並catch了InterruptedException
此時發現MyThread中拋出了InterruptedException,但是案例一中並沒有拋出
所以對於處在sleep()方法阻塞下的線程,interrupt()方法會使線程拋出一個異常。
案例三:
public class ThreadInterruptTest2 {
public static void main(String[] args) {
try {
Thread t = new MyThread2();
t.start();
Thread.sleep(1000);
t.interrupt(); // 中斷t線程
System.out.println("before main join");
t.join(); // 等待t線程結束
System.out.println("end");
} catch (InterruptedException e) {
System.out.println("main interrupted!");
}
}
}
class MyThread2 extends Thread {
public void run() {
Thread hello = new HelloThread();
hello.start(); // 啓動hello線程
try {
hello.join(); // 等待hello線程結束
} catch (InterruptedException e) {
System.out.println("mythread interrupted!");
}
hello.interrupt();
}
}
class HelloThread extends Thread {
public void run() {
int n = 0;
while (!isInterrupted()) {
n++;
System.out.println(n + " hello!");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("hello interrupted");
break;
}
}
}
}
Output:
1 hello!
2 hello!
3 hello!
4 hello!
5 hello!
6 hello!
7 hello!
8 hello!
9 hello!
10 hello!
before main join
mythread interrupted!
hello interrupted
end
比案例二中更復雜了,嵌套線程調用
但是基本邏輯一樣,就是在調用線程中斷方法,線程的具體實現run中具有join調用,會拋出InterruptedException
所以對於處在sleep()、wait()和join()方法阻塞下的線程,interrupted方法會使線程拋出一個異常。
總結:
interrupt()不會去真正意義上的打斷一個正在運行的線程,而是修改這個線程的中斷狀態碼(interrupt status)。同時,對於處在sleep()、wait()和join()方法阻塞下的線程,該方法會使線程拋出一個異常。
與interrupt類似的方法
java.lang.Thread#isInterrupted()
判斷目標線程是否被中斷,不會清除中斷標記。
java.lang.Thread#interrupted
判斷目標線程是否被中斷,會清除中斷標記。