2

让我们假设线程 t1 正在运行(即没有处于睡眠、等待或加入状态)。另一个线程 t2 中断 t1。Javadoc 说将设置 t1 的中断状态。

让我们假设 t1 稍后进入睡眠、等待或加入状态。发生什么了?

InterruptedExceptioni)由于线程 t1 处于中断状态,线程 t1 是否会自动引发?

假设 t1 仍处于睡眠、等待或加入状态。让我们假设 t2 再次中断 t1:

ii) 线程 t1 是由 an 引发InterruptedExecution还是需要通过调用interrupted()first 来清除其中断状态?

这个有官方的Java立场吗?谢谢。

4

2 回答 2

2

在第一种情况下(“i”),是的,睡眠线程将通过被抛出Thread#sleep()的方式从其调用中弹出。InterruptedException此时,由 表示的线程的状态标志Thread#isInterrupted()将被清除;调用Thread#isInterrupted()将返回 false。由于InterruptedException处于飞行状态,消息已发送给所有传递调用者。

然后,调用者有责任捕获该异常并执行以下两项操作之一:

  • 要么退出当前线程,要么
  • 调用Thread#interrupt()当前线程(即Thread.currentThread().interrupt()

当您说线程“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一书。

于 2011-11-24T15:47:11.773 回答
1

检查线程的中断状态会清除状态标志;也就是说,引发 an 的代码InterruptedException正在清除状态,就像您自己的代码手动采样状态一样。

于 2011-11-24T11:57:23.713 回答