Java没有提供任何机制来安全的终止线程。但是它提供了中断这种协作机制,能够使一个线程终止另一个线程的当前工作。也就是说Java的中断机制是协同式的,而不是抢占式的。
调用线程的interrupt()方法并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。对中断正确的理解是:它并不会真正的中断一个正在运行的线程,而是发出了中断的请求,将线程的中断状态设置成true,让线程在合适的时刻中断自己,至于中不中断,什么时候中断,在哪中断都由目标线程执行的任务控制。
public class ThreadInterrupt1 extends Thread {
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Someone interrupted me.");
} else {
System.out.println("Going...");
}
long now = System.currentTimeMillis();
while (System.currentTimeMillis() - now < 1000) {
// 为了避免Thread.sleep()而需要捕获InterruptedException而带来的理解上的困惑,
// 此处用这种方法空转1秒
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadInterrupt1 t = new ThreadInterrupt1();
t.start();
Thread.sleep(3000);
t.interrupt();
}
}
上面代码执行的结果如下:
虽然主线程调用了ThreadInterrupt1线程实例的interrupt()方法将中断状态设置成了true,但是ThreadInterrupt1定义的任务代码中未处理中断的情况,仍然继续执行。
可见interrupt()方法并不一定能终止线程。
但是如果代码修改如下:
public class ThreadInterrupt1 extends Thread {
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Someone interrupted me.");
} else {
System.out.println("Going...");
}
// long now = System.currentTimeMillis();
// while (System.currentTimeMillis() - now < 1000) {
// // 为了避免Thread.sleep()而需要捕获InterruptedException而带来的理解上的困惑,
// // 此处用这种方法空转1秒
// }
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
System.out.println("loop end flag!");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadInterrupt1 t = new ThreadInterrupt1();
t.start();
Thread.sleep(3000);
t.interrupt();
}
}
程序运行结果如图:
线程中断后程序未继续执行输出“loop end flag!”,
一般来说,抛出InterruptedException的方法是可中断的(没有在方法中处理中断请求却也抛出InterruptedException的除外)即可中断方法可以对interrupted()方法做出响应,类似sleep方法,自定义的可中断方法在适合处理中断的地方检查中断状态并处理。
在捕获InterruptedException后线程的中断状态被设置成false.
绝大多数可中断的阻塞方法会在方法的入口检查中断状态,并在发现该状态被设置成true后立刻抛出InterruptedException(通常,可中断方法会在阻塞之前或者进行重要工作前检查中断状态,从而尽快地响应中断).