Java的Thread.sleep在什么情况下会抛出InterruptedException?

132

Java的Thread.sleep什么时候会抛出InterruptedException异常?忽略它是否安全?我没有进行多线程操作,只是想在重试某些操作之前等待几秒钟。


2
https://dev59.com/-XNA5IYBdhLWcg3wSrqa - Jeremy Stein
1
取决于你对“忽略”一词的理解。InterruptedException是一个被捕获的异常,因此你必须在任何调用线程的join或sleep方法,或在对象上调用wait()的方法中处理或声明此类型的异常,否则代码将无法编译。 - 8bitjunkie
8个回答

57

通常情况下,您不应忽略异常。请参考以下论文:

Don't swallow interrupts

Sometimes throwing InterruptedException is not an option, such as when a task defined by Runnable calls an interruptible method. In this case, you can't rethrow InterruptedException, but you also do not want to do nothing. When a blocking method detects interruption and throws InterruptedException, it clears the interrupted status. If you catch InterruptedException but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to. This task is accomplished by calling interrupt() to "reinterrupt" the current thread, as shown in Listing 3. At the very least, whenever you catch InterruptedException and don't rethrow it, reinterrupt the current thread before returning.

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) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}

在此处查看整篇论文:

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-


52
如果抛出InterruptedException异常,意味着有些东西想要中断(通常是终止)该线程。这是通过调用线程的interrupt()方法触发的。等待方法检测到这一点,并抛出InterruptedException,因此catch代码可以立即处理终止请求,并且不必等到指定的时间结束。
如果您将其用于单线程应用程序(以及某些多线程应用程序),则永远不会触发该异常。通过具有空catch子句来忽略它并不推荐。抛出InterruptedException会清除线程的中断状态,因此如果不正确处理该信息就会丢失。因此,我建议运行:
} catch (InterruptedException e) {
  Thread.currentThread().interrupt();
  // code for stopping current task so thread stops
}

再次设置状态后,结束执行。即使从未使用过,这样做也是正确的行为。

更好的方法可能是添加以下内容:

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

这意味着将此代码块的语句转移到catch块中。基本上意味着它绝不能发生。因此,如果在可能发生该情况的环境中重复使用代码,则会对其进行投诉。


6
在Java中,断言默认是关闭的。因此最好只需抛出一个RuntimeException异常。 - Evgeni Sergeev

13

我强烈推荐《Java专家通讯》(The Java Specialists newsletter),该通讯刊登了一篇关于这个问题的有趣文章,并介绍了如何处理InterruptedException。这篇文章非常值得阅读和消化。


10
它说了什么? - theonlygusti
好的文章链接,但是有些无意义。你会调用stop()的原因是因为出现了问题,比如一个无限循环的servlet,你想要杀掉它并希望一切顺利。这与检查异常的无意义混淆在一起。就像所有其他检查异常一样,只需将其包装在throw new RuntimeException中即可。 - Tuntable
感谢您参考本文!由于“InterruptedException”的命名方式,我有些困惑线程是停止执行还是暂停执行。这篇文章解决了这个小问题的疑虑。 - Melvin

4

Thread类中的sleep()wait()方法可能会抛出InterruptedException异常。如果其他线程想要中断等待或睡眠的线程,就会发生这种情况。


3

在单线程代码中处理它的一种可靠而简单的方法是捕获并将其重新抛出为RuntimeException,以避免需要在每个方法中声明它。


1
文档中可以得知:
当线程正在等待、睡眠或者忙于其他操作时,如果该线程在活动期间或之前被中断,则会抛出一个InterruptedException异常。
换句话说,当某些代码调用特定线程上的interrupt()方法时,就会发生InterruptedException。它是一个已检查异常,在Java中许多阻塞操作都可能会抛出该异常。
中断系统的目的是提供一种替代工作流程,以允许线程中断其他线程中的任务。中断不一定会中断运行中的线程,但它也可以请求线程在下一个方便的机会中断自身。
线程可能会因为以下几个原因而被阻塞:
- 等待从Thread.sleep()中唤醒 - 等待锁的获取、等待I/O完成 - 等待另一个线程的计算结果等。 InterruptedException通常会由所有阻塞方法抛出,以便处理并执行纠正操作。
然而,在大多数情况下,由于我们的代码是Runnable的一部分,所以在这种情况下,我们必须捕获它并恢复状态。
Java中有一些方法会抛出code>InterruptedException。例如:
- Object类: - Thread.sleep() - Thread.join() - wait() - BlockingQueue: - put() - take()

-1

从个人经验来看,我只是将 thread.sleep() 改为 this.sleep()


2
目前来看,您的回答不太清楚。请编辑并添加更多细节,以帮助其他人理解它如何解答所问的问题。您可以在帮助中心找到有关如何撰写良好答案的更多信息。 - Community

-7

InterruptedException通常在睡眠被中断时抛出。


14
这是错误的,因为打断的不是睡眠本身,而是运行睡眠的线程。被打断是线程的一种状态。这只会导致睡眠方法被退出。 - ubuntudroid

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