java - 为什么 InterruptedException 仅从阻塞方法(如 sleep() 和 wait())中抛出?

标签 java multithreading wait sleep interrupted-exception

如果我写如下代码,我们不能中断或终止线程。它也不会抛出 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();

我的问题是,

  1. 为什么 Java 的设计方式是 InterruptedException 仅在阻塞方法(如 sleep() 和 wait())的情况下抛出。

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

我看了那么多关于InterruptedException的博客和文章,都没有找到有说服力的答案。

编辑

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

最佳答案

1) why Java is designed in such way that InterruptedException is being thrown only in case of blocking methods like sleep() and wait().

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

引用自tutorial on the subject , 强调我的。

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate.

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

2) Why in normal code, we need to handle this manually as in my above code snippet? Why Java is not throwing InterruptedException whenever we set interrupted flag true through interrupt() method?

替代方案是让 InterruptedException 成为一个 RuntimeException,无论程序是否预料到它,它都可以随时抛出。 stop() 和其他已弃用的 Thread 方法的部分问题在于它们往往会违反各种语言结构,并且可能会离开 应用程序内存处于错误状态。这是 more details about that .

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

if (Thread.interrupted()) {

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

if (Thread.currentThread().isInterrupted()) {

这保留了中断标志,如果可能应该这样做。此外,当 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
}

库“吞噬”中断标志的问题很多。即使您的代码很小,它也可能会被复制到更大的 block 中,因此您始终可以将中断标志恢复为良好模式。

关于java - 为什么 InterruptedException 仅从阻塞方法(如 sleep() 和 wait())中抛出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43823298/

相关文章:

java - 静态同步方法

c# - HttpClient Async 方法会在新线程中运行吗

Python 共享库

java - 线程同步——如何交替执行线程

c - wait() 和 exit() 与父子进程

java - 如何在WebClient响应中提取http header ?

java - Android 9.0 Java.net.URL

c++ - 一个线程等待多个线程的信号机制

c++ - WEXITSTATUS 始终返回 0

java - 为什么 ListView 不在 Wicket 口中重复 List<String> ?