开启掘金成长之旅!这是我参与「掘金日新计划 · 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)
通过判断中断状态
1、但是如果pos_1位置有一个很费时的IO操作,就没有机会执行到if判断那里,也就不能关闭线程。所以就需要下面的暴力方法
暴力关闭(守护线程)
以上三种关闭线程的使用场景:分布式文件拷贝,如果拷贝的时间过长,则关闭该程序,防止程序一直阻塞。或者其他执行耗时很长的任务守护线程的应用场景有很多