线程常用方法 interrupt


一、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() 方法重新设置打断标记