为什么 InterruptedException 只从 sleep() 和 wait() 等阻塞方法抛出?

Abh*_*iya 1 java multithreading sleep wait interrupted-exception

如果我编写如下代码,我们不能中断或终止线程。它也不会抛出 InterruptedException。

Thread loop = new Thread(
  new Runnable() {
    @Override
    public void run() {
      while (true) {
      }
    }
  }
);
loop.start();
loop.interrupt();
Run Code Online (Sandbox Code Playgroud)

要中断这个线程,我需要修改我的代码如下:

Thread loop = new Thread(
  new Runnable() {
    @Override
    public void run() {
      while (true) {
        if (Thread.interrupted()) {
          break;
        }
        // Continue to do nothing
      }
    }
  }
);
loop.start();
loop.interrupt();
Run Code Online (Sandbox Code Playgroud)

我的问题是,

  1. 为什么 Java 的设计方式是只有在像 sleep() 和 wait() 这样的阻塞方法的情况下才会抛出InterruptedException

  2. 为什么在普通代码中,我们需要像上面的代码片段那样手动处理?为什么每当我们通过interrupt()方法将中断标志设置为 true 时,Java 不会抛出 InterruptedException ?

我已经阅读了很多关于 InterruptedException 的博客和文章,但没有找到任何令人信服的答案。

编辑

找到关于 InterruptedException 的好文章:http : //codepumpkin.com/interruptedexception-java-multithreading/

Gra*_*ray 5

1) 为什么 Java 的设计方式是只有在像 sleep() 和 wait() 这样的阻塞方法的情况下才会抛出 InterruptedException。

重点thread.interrupt()是它是合作的。一个线程被中断,但它必须检查中断标志,Thread.currentThread().isInterrupted()以便它可以正确管理自己的终止并在必要时清理共享对象、锁、finally 块等。

引用有关该主题教程,重点是我的。

中断是对线程的指示,它应该停止正在执行的操作并执行其他操作。它是由程序员来决定究竟是如何一个线程响应一个中断,但它是很常见的线程终止。

这些方法InterruptedException是正在等待的锁和其他条件的人。它们在被中断时抛出异常,因此线程可以在终止之前再次清理自己。

2)为什么在普通代码中,我们需要像上面的代码片段一样手动处理?为什么每当我们通过 interrupt() 方法将中断标志设置为 true 时,Java 不会抛出 InterruptedException?

另一种选择InterruptedException是 aRuntimeException可以随时抛出,而不管程序是否预料到它。与stop()其他不推荐使用的Thread方法的部分问题是它们倾向于违反各种语言结构,并且可能会使应用程序内存处于不良状态。这里有更多的细节

同样可以说对InterruptedException,如果它是一个RuntimeException。您可以想象一个线程是否正在更改共享对象,然后只是在中途抛出意外RuntimeException或完全停止。正在更新的共享对象很容易处于无效状态。

if (Thread.interrupted()) {
Run Code Online (Sandbox Code Playgroud)

这不是正确的调用方法,因为它会清除线程上的中断标志,这是一种错误模式。请使用以下内容:

if (Thread.currentThread().isInterrupted()) {
Run Code Online (Sandbox Code Playgroud)

这会保留中断标志,如果可能的话应该这样做。此外,当InterruptedException抛出时也会清除中断标志。这就是为什么这是一个很好的模式:

try {
   ...
} catch (InterruptedException ie) {
   // re-interrupt the thread to propagate the interrupt flag
   Thread.currentThread().interrupt();
   // handle the interrupt here by probably quitting the thread
}
Run Code Online (Sandbox Code Playgroud)

库“吞下”中断标志有很多问题。即使您的代码很小,它也可能会被复制到一个更大的块中,因此您总是可以将中断标志恢复为一个好的模式。