在第一种情况下(“i”),是的,睡眠线程将通过被抛出Thread#sleep()
的方式从其调用中弹出。InterruptedException
此时,由 表示的线程的状态标志Thread#isInterrupted()
将被清除;调用Thread#isInterrupted()
将返回 false。由于InterruptedException
处于飞行状态,消息已发送给所有传递调用者。
然后,调用者有责任捕获该异常并执行以下两项操作之一:
当您说线程“t1”“仍处于睡眠、等待或加入状态”时,它在初始调用Thread#sleep()
exited via之后的唯一可能方式InterruptedException
是它是否捕获了异常、忽略它并调用了一些异常Thread.sleep()
在线程“t2”有机会再次中断它之前再次阻塞方法。
如果线程“t2”要再次中断线程“t1”,而“t1”当前在可中断方法调用上被阻塞,“t1”的调用将再次以 退出InterruptedException
。否则,将设置线程的中断标志以供以后检测。
每次调用Thread#interrupt()
,该目标线程的中断状态将被设置为“真”,这意味着该线程自上次清除其中断状态以来一直被中断。下一次被中断的线程尝试对可中断方法进行阻塞调用时,线程的中断状态将被清除,方法将抛出InterruptedException
。
请注意,像这样清除中断状态不会丢失信息,只要清除后立即抛出即可InterruptedException
。抛出InterruptedException
的最好解释为,“该线程在之前的某个时间点设置了其中断状态,现在您有责任做出反应,并且通常会警告后续调用者预期的中断。” Thread#interrupt()
您通过在捕获后调用来实现后一个目标,将中断状态InterruptedException
恢复给其他人看到。
有关该协议的更权威的描述,请参阅Java Concurrency in Practice一书。