JAVA线程-interrupt
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
判断目标线程是否被中断,会清除中断标记。