Thread 之 interrupt、isInterrupted、interrupted 方法
interrupt(): 打断 sleep、wait、join 的线程会抛出 InterruptedException 异常并清除打断标记,如果打断正在运行的线程、park 的线程则会重新设置打断标记
isInterrupted(): 不会清除打断标记
interrupted(): 会清除打断标记
一、调用 interrupt() 方法中断正在运行的线程
@Slf4j
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
}
});
t1.start();
// 先让 t1 线程运行
TimeUnit.SECONDS.sleep(1);
// isInterrupted() 可以获取到线程的打断标记,如果线程被打断,则打断标记为 true,并且该方法不会清除打断标记
log.info("before interrupt status >>> {}", t1.isInterrupted());
// 打断正在运行的线程/park 状态的线程会重新设置打断标记,打断 sleep、join、wait 状态的线程会抛出 InterruptedException 异常,并且会清除打断标记
t1.interrupt();
log.info("after interrupt status >>> {}", t1.isInterrupted());
}
}
中断正在运行的线程时,线程的中断状态变成 true,线程正常运行,并不会停止下来
调用 interrupt() 方法中断处于 sleep、wait、join 状态的线程
@Slf4j
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
// t1 线程休眠 1000s
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
log.info("{} 线程被打断了", Thread.currentThread().getName());
}
}, "t1");
t1.start();
// 主线程休眠 2s,让 t1 线程有足够的时间进入 sleep 状态
TimeUnit.SECONDS.sleep(2);
log.info("before interrupt status >>> {}", t1.isInterrupted());
t1.interrupt();
// 主线程休眠 2s,让 t1 线程有足够的时间进行 interrupt 操作
TimeUnit.SECONDS.sleep(2);
log.info("after interrupt status >>> {}", t1.isInterrupted());
}
}
中断处于 sleep、join、wait 状态的线程会抛出异常,并且会将中断状态重置为 false
中断时线程的状态 | 中断后线程的中断标记 | 中断后线程运行情况 |
正常运行的线程 | false -> true | 线程正常运行 |
sleep、wait、join 状态的线程 | false -> true -> false | 线程抛出异常,中止运行 |
然后再看一下 isInterrupted 和 interrupted 的区别
先看一下 isInterrupted() 方法源码
public boolean isInterrupted() {
// ClearInterrupted 参数的含义是否清除打断标记
// false 代表不清除,打断之后 false -> true
// true 代表清除,打断之后会重置打断标记 false -> true -> false
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
接着再看一下 interrupted() 方法源码
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);
从上面的源码中可以看出 isInterrupted() 方法和 interrupted() 方法实际上底层都是调用 private native boolean isInterrupted(boolean ClearInterrupted) 方法,唯一的区别就是传递的参数,一个是 false,一个是 true,也就是一个不会清除打断标记,另外一个会清除打断标记
线程调用 interrupt() 方法并不会真正中断线程,而是让线程具有响应中断的能力,如果你可以在 main 线程中随意的去停止 t1 线程,而 t1 线程却毫无察觉,这不是一件很可怕的事情吗,真正中断的操作应该由 t1 线程去决定,而不是 main 线程,常用的做法是在 t1 线程中根据打断标记去执行不同的逻辑