线程的interrupted、wait、join

76 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

InterruptedException

它是一个特殊的异常,不是说 JVM 对其有特殊的处理,而是它的使用场景比较特殊。通常,我们可以看到,像 Object 中的 wait() 方法,ReentrantLock 中的 lockInterruptibly() 方法,Thread 中的 sleep() 方法等等,这些方法都带有 throws InterruptedException,我们通常称这些方法为阻塞方法(blocking method)。

阻塞方法一个很明显的特征是,它们需要花费比较长的时间(不是绝对的,只是说明时间不可控),还有它们的方法结束返回往往依赖于外部条件,如 wait 方法依赖于其他线程的 notify,lock 方法依赖于其他线程的 unlock等等。

当我们看到方法上带有 throws InterruptedException 时,我们就要知道,这个方法应该是阻塞方法,我们如果希望它能早点返回的话,我们往往可以通过中断来实现。

除了几个特殊类(如 Object,Thread等)外,感知中断并提前返回是通过轮询中断状态来实现的。我们自己需要写可中断的方法的时候,就是通过在合适的时机(通常在循环的开始处)去判断线程的中断状态,然后做相应的操作(通常是方法直接返回或者抛出异常)。当然,我们也要看到,如果我们一次循环花的时间比较长的话,那么就需要比较长的时间才能感知到线程中断了。

wait中断测试

public static void main(String[] args) {

    Thread t = new Thread() {
        @Override
        public void run() {
            while (true) {
                synchronized (MONITOR) {
                    try {
                        MONITOR.wait(10);
                    } catch (InterruptedException e) {
                        System.out.println("wait响应中断");//pos_1
                        e.printStackTrace();//pos_2
                        System.out.println(isInterrupted());//pos_3
                    }
                }
            }
        }
    };

    t.start();
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        System.out.println("sleep响应中断");
        e.printStackTrace();
    }
    System.out.println(t.isInterrupted());//pos_4
    t.interrupt();
    System.out.println(t.isInterrupted());//pos_5
}

注释掉e.printStackTrace();的输出

false //pos_4
true //pos_5
wait响应中断 //pos_1
false //pos_3

1、pos_2这里join的是main线程,所以pos_1这里需要中断main线程,才能收到中断信息。

关闭线程

优雅的关闭(通过一个Boolean)

image.png

通过判断中断状态

image.png

1、但是如果pos_1位置有一个很费时的IO操作,就没有机会执行到if判断那里,也就不能关闭线程。所以就需要下面的暴力方法

暴力关闭(守护线程)

image.png

image.png

以上三种关闭线程的使用场景:分布式文件拷贝,如果拷贝的时间过长,则关闭该程序,防止程序一直阻塞。或者其他执行耗时很长的任务守护线程的应用场景有很多