如果我按如下方式编写代码,则无法中断或终止线程。同样,它不会抛出InterruptedException。

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

要中断此线程,我需要修改我的代码,如下所示:
Thread loop = new Thread(
  new Runnable() {
    @Override
    public void run() {
      while (true) {
        if (Thread.interrupted()) {
          break;
        }
        // Continue to do nothing
      }
    }
  }
);
loop.start();
loop.interrupt();

我的问题是
  • 为什么Java的设计方式是仅在阻塞sleep()和wait()之类的情况下才抛出 InterruptedException
  • 为什么在普通代码中,我们需要像上面的代码片段中那样手动处理它?当我们通过 interrupt()方法将中断标志设置为true时,为什么Java不抛出InterruptedException?

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

    编辑

    在InterruptedException上找到了不错的文章:
    http://codepumpkin.com/interruptedexception-java-multithreading/

    最佳答案


    thread.interrupt()的全部要点是它是协作的。线程被中断,但是它必须使用Thread.currentThread().isInterrupted()检查中断标志,以便它可以正确管理其自身的终止,并在必要时清理共享对象,锁,最终块等。

    引用tutorial on the subject,重点是我的。



    确实会引发InterruptedException的方法是在锁和其他条件下等待的方法。它们在被中断时会引发异常,因此线程可以在终止之前自行进行清理。



    另一种选择是让InterruptedException是一个RuntimeException,无论程序是否预期它,都可以随时抛出它。 stop()和其他不推荐使用的Thread方法的部分问题是,它们倾向于违反各种语言结构,并可能离开
    应用程序内存处于错误状态。这是more details about that

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



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



    这将保留中断标志,如果可能的话,应执行此操作。同样,当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
    }
    

    库“吞噬”中断标志存在许多问题。即使您的代码很小,也可能将其复制到一个较大的块中,因此您始终可以将中断标志恢复为一个好的模式。

    10-08 15:10