InterruptedException由Sun Microsystems公司的前任工程师Frank Yellin编写,发布于JDK1.0沿用至今,不过它并不是一个常见的Exception,只有在直接或间接调用如下方法的时候才会触发它
java.lang.Object | java.lang.Thread |
---|---|
wait() | join() |
wait(long) | join(long) |
wait(long, int) | join(long, int) |
sleep(long) | |
sleep(long, int) |
以上方法可都会throws出InterruptedException,但InterruptedException并不常见,例如Thread.sleep(long)
就经常被用来休眠线程,却很少会遇到InterruptedException,那么在什么情况下才会触发它呢?请看demo1
// demo1
Thread.currentThread().interrupt();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread中interrupt()方法是个关键,它使线程陷入中断状态,在中断状态中调用sleep方法,立刻触发如下异常
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
...
这是正确的结果,因为demo1调用interrupt()
中断了线程,然后又休眠线程,这是不合理的。
但是这又是有用的,正如sleep()的Javadoc中所说
@throws InterruptedException
if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
意思是说,如果当前线程被中断,则会抛出此异常,并且清除当前线程的中断状态。
那么中断状态被清除掉之后,是否就可以使用sleep()呢?下面尝试一下在demo1的catch块中再次sleep
// demo2
Thread.currentThread().interrupt();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
try {
Thread.sleep(200);
System.out.println("success");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
此时demo2成功运行,没有进入第二个catch块,输出
success
在单线程的情况下并不容易遇到,因为在线程interrupt后休眠线程不合情理,也很少有情况会interrupt当前的线程,但在多线程的情况下,就不易感觉到
// demo3
Thread foo = new Thread(() -> {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
foo.start();
foo.interrupt();
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
...
线程foo启动后调用了interrupt()
,此时foo尚未正式运行,因为启动线程需要一定的时间,foo被interrupt后开始运行,执行sleep时再次出现与demo1相同的问题,问题的关键就在于demo1和demo3都要休眠一个处于中断状态的线程,InterruptedException自然会随之而来。
总结
如果一个线程被interrupt,并在之后进行sleep,wait,join这三种操作,那么InterruptedException就会被触发
网友评论