为什么我们不应该直接忽略InterruptedException异常

6

我很困惑,不明白为什么InterruptedException不应该被忽略。

IBM的文章指出:

当阻塞方法检测到中断并抛出InterruptedException时,它会清除中断状态。如果你捕获了InterruptedException但无法重新抛出它,你应该保留中断发生的证据,以便调用堆栈上层的代码可以知道中断并在需要时做出响应。

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;

    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }

    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
           Thread.currentThread().interrupt();//preserve the message
             return;//Stop doing whatever I am doing and terminate

         }
    }
}

另外,《Java并发编程实践》在第7.1.3章节中更详细地讨论了此问题。它的规则是:

只有实现线程中断策略的代码可以忽略中断请求。通用任务和库代码永远不应忽略中断请求。

1.有人能解释一下当线程被终止时,如何使高调用堆栈中的代码利用在catch块中由Thread.currentThread().interrupt()设置的状态吗?

请解释上述规则。


你不明白“这样上层调用栈中的代码就可以了解中断并在需要时做出响应”的部分吗? - user207421
@EJP 代码如何了解中断以及如何处理它呢?可能一个例子会有所帮助。 - beinghuman
1个回答

6

请看下面的例子,假设它在一个线程/线程池上下文中运行。

public void run() {
  // Honor interrupts so that you can stop/kill the task
  while (!Thread.currentThread().interrupted()) {
    this.doSomeChunkOfWork();
  }    
}

上面的代码是一个很好的例子,展示了如何编写一个可以被中断并以块处理数据的任务(比如从某个源读取并分块处理数据)。现在假设 doSomeChunkOfWork 被中断并抛出了异常。如果你不再次设置标志或者保持标志的中断状态,run 方法将无法知道方法调用返回时是否被中断,这将破坏我们良好的逻辑。
这就是为什么你总是要重新设置状态,以便方法调用链下方的方法知道线程到底是否被中断。我希望为此想出一个类比:“不要把污垢藏在地毯底下”。 :)

你正在使用同一调用栈来处理它。我想知道的是线程的创建者如何处理它。 - beinghuman
1
@NikhilArora:那么,你需要编辑你的问题,因为它问道“任何人能解释一下如何在更高的调用堆栈中使用设置的状态”。 - Sanjay T. Sharma
1
@NikhilArora:另外,如果线程“main”创建了一个名为“A”的线程,“main”将不会意识到针对线程“A”的中断,因此您的问题并不是很清楚。 - Sanjay T. Sharma
1
@NikhilArora - 线程的创建者不在所创建线程的“调用堆栈”中,因此您的陈述毫无意义。新创建的线程具有全新的调用堆栈,与创建者的调用堆栈无关。 - jtahlborn
@jtahlborn 您是正确的。我已经编辑了问题。您可以检查一下。 - beinghuman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接