如果我自己不打断任何内容,我是否必须担心InterruptedExceptions?

时间:2009-06-21 20:06:56

标签: java exception concurrency

我在爱好项目中使用java.util.concurrent.Semaphore。它用在我写的连接池类中。我可以毫不费力地使用它,除了这个方法:

public void acquire(int permits) throws InterruptedException

迫使我处理InterruptedException。现在,我不确定什么“打断”一个线程甚至意味着我在我的代码中从不这样做(好吧,不是明确地说)。这是否意味着我可以忽略该异常?我该怎么处理呢?

5 个答案:

答案 0 :(得分:28)

是的,您需要担心InterruptedException,就像您需要担心任何其他必须抛出或处理的已检查异常一样。

大部分时间InterruptedException表示停止请求,很可能是由于运行代码的线程为interrupted这一事实。

在您等待获取连接的连接池的特定情况下,我会说这是一个取消问题,您需要中止采集,清理并恢复中断的标志(见下文)。


例如,如果您在Runnable内使用某种Callable / Executor,那么您需要正确处理InterruptedException:

executor.execute(new Runnable() {

    public void run() {
         while (true) {
              try {
                 Thread.sleep(1000);
              } catch ( InterruptedException e) {
                  continue; //blah
              }
              pingRemoteServer();
         }
    }
});

这意味着您的任务永远不会遵循执行程序使用的中断机制,也不允许正确的取消/关闭。

相反,正确的习惯用法是恢复中断状态然后停止执行:

executor.execute(new Runnable() {

    public void run() {
         while (true) {
              try {
                 Thread.sleep(1000);
              } catch ( InterruptedException e) {
                  Thread.currentThread().interrupt(); // restore interrupted status
                  break;
              }
              pingRemoteServer();
         }
    }
});

有用资源

答案 1 :(得分:6)

不。只有在您自己中断线程时才会生成InterruptedException。如果您自己不使用Thread.interrupt(),那么我会将其重新抛出为某种“意外异常”或将其记录为错误并继续前进。例如,在我的代码中,当我被迫抓住InterruptedException并且我从不打电话给interrupt()时,我做的相当于

catch (InterruptedException exception) {
    throw new RuntimeException("Unexpected interrupt", exception);
}

如果是意料之外的话。有很多地方我故意打断我的线程,在那些情况下我以明确的方式处理InterruptedException。通常是通过退出我所处的循环,清理,然后停止线程。

答案 2 :(得分:1)

可以通过调用Thread.interrupt()来中断线程。它用于优雅地发信号通知它应该做其他事情。通常它会导致阻塞操作(例如Thread.sleep())提前返回并抛出InterruptedException。如果线程被中断,则会在其上设置一个标志。可以通过Thread.isInterrupted()调用查询此标志。

如果你不使用线程中断并仍然得到这个异常,你可以退出你的线程(并且最好记录异常)。

通常,它取决于您的多线程应用程序的功能。

答案 3 :(得分:1)

如果您不知道如何在方法中处理它,我建议您在方法中使用throws InterruptedException(以及调用者等)声明它

如果它是你永远不会发生的事情,我会抓住它并将其包装在AssertionError中。

答案 4 :(得分:0)

在执行了线程所需的任何清理后,您应该退出run()方法 HTH