为什么我们不应该吞下InterruptedException

bei*_*man 6 java concurrency interrupted-exception

我很困惑,无法理解为什么不应该吞下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

         }
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,Java Concurrency in Practice在第7.1.3章:响应中断中更详细地讨论了这一点.它的规则是:

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

任何人都可以解释高级调用堆栈中的代码如何利用Thread.currentThread()设置的状态.insert(); 在线程终止时在catch块中?

还请解释上面的规则?

San*_*rma 5

看一下这个让我们假设在线程/线程池上下文中运行的例子.

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

上面的代码是一个很好的例子,说明如何编写一个可以被中断的任务并以块的形式处理数据(想想从一些源读取和处理部分数据).现在让我们假设doSomeChunkOfWork被中断并且您捕获异常.除非你再次设置标志或保持标志的中断状态,否则run当方法调用返回时,方法将无法知道调用堆栈内部的处理被中断,这会弄乱我们的良好逻辑.

这就是为什么总是将状态设置回来以便调用堆栈中的方法知道线程是否真正中断的原因.我想要的一个类比是"不要在地毯下扫除污垢".:)