一、Thread.sleep() 为什么要抛出 InterruptedException
其实最主要的目的是为了让被打断的线程具有响应中断的能力(打断只是设置标记而已,目的是为了让被打断的线程拥有感知能力,是否应该被打断由自己控制,而不是由外部的线程去决定)
具体可以参考这篇博客,写的挺好的 https://blog.csdn.net/u011403239/article/details/119849670
二、如何在一个线程中优雅的关闭另外一个线程
1、调用 stop 方法
stop 方法会真正的杀死线程,但是如果在杀死指定线程的那一刻该线程锁住了一些共享资源的话,那么当该线程被杀死后就再也没有机会释放锁,其它的线程就再也无法获取到锁,也就不能访问到某些共享资源了
2、System.exit(int)
我们的目的仅仅是为了停止某一个线程,但这种做法会让整个程序都停止运行
3、interrupt
@Slf4j
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = () -> {
while(true){
if(Thread.currentThread().isInterrupted()){
log.info(Thread.currentThread().getName()+" 线程发生中断,退出循环");
break;
}
try {
Thread.sleep(3*1000);
// 打断非阻塞状态的线程,抛出 InterruptedException 之后不会擦除打断标记
log.info("执行任务");
} catch (InterruptedException e) {
e.printStackTrace();
log.info("打断阻塞状态的线程(sleep、wait、join),抛出 InterruptedException 之后,打断标记为: {}",Thread.currentThread().isInterrupted());
// 调用 interrupt() 方法,将打断标记置为 true
Thread.currentThread().interrupt();
log.info("调用 interrupt() 方法之后,打断标记为: {}",Thread.currentThread().isInterrupted());
}
}
};
Thread t1 = new Thread(runnable, "t1");
t1.start();
log.info("main 线程 start...");
Thread.sleep(5 *1000);
// 在 main 线程中调用 interrupt() 方法中断 t1 线程
t1.interrupt();
}
}
执行结果
阻塞状态的线程被打断会抛出 InterruptedException,并且会擦除打断标记,所以需要再次调用 interrupt() 方法重新设置打断标记