如果没有人调用 interrupt(),是否可以忽略 InterruptedException?

如果我创建自己的线程(即不是线程池)并且调用了某个地方或任何其他可中断的方法,如果我知道代码中没有其他人在线程上执行中断,是否可以忽略DistrutheatedException。sleep

换句话说,如果线程应该像JVM一样长地存在,这意味着线程是不可中断的,那么是否可以安全地假设DistrutedException永远不会被调用,因此可以吞噬异常?


答案 1

忽略已检查的异常永远不会被认为是安全的。
目前对你来说似乎没问题,但是如果任何其他程序员使用你的代码/API,他们应该期待标准行为:

  • 也就是说,线程对中断调用“做出反应”,使用线程的文档描述的任何“反应”。

  • 我的意思是,线程的开发人员可以决定并准确记录线程如何处理中断,而Java没有任何预定义的规则,但您应该记录线程的“反应”(带有文档注释)。

  • 例如,仅从阻塞方法(如 )中抛出 ,但从不从正常代码行中抛出(这意味着默认情况下只是忽略中断),这允许开发人员选择(并记录)线程的反应,例如:InterruptedExceptionThread.sleep(...)

    • 也许中,通过在进度中取消任务。

    这需要时间来开发,如果尚未得到支持。

    • 也许通过调用 catch-block 来推迟(或软忽略)。Thread.currentThread().interrupt()

    它模拟在正常代码运行时发生的中断。

    • 可能崩溃,通过抛出一个(或子类),并将 -instance 作为 传递。java.lang.ErrorInterruptedExceptioncause

    除非有记录,否则是最不想要或期望的。

解释推迟;空的 catch 块对于 是危险的,因为 JVM 会删除中断的标志,并且肯定应该在 catch 块中再次设置它,例如:InterruptedException

try {
    Thread.sleep(1000);
} catch (InterruptedException ignored) {
    Thread.currentThread().interrupt();
}

在我看来,这是 s 的最小捕获实现。在循环中检查标志也不会有太大伤害。
与你未来的程序员自己在一两天内寻找意外线程行为的麻烦相比,这几乎没有开销,因为你的项目可能已经增长了一点。InterruptedExceptionisInterrupted

如果您觉得代码的可读性受到这些 catch 实现的影响,则可以实现自己的实用程序方法,该方法负责处理 s 并正确设置标志。safeSleepException

另一方面,在硬件故障的情况下,JVM本身不会抛出,它只是用户指示的异常因此,如果您不传播 Thread的引用,则不会有任何其他 Thread能够在其上调用 Thread.interrupt()。从技术上讲就是这样。但你不应该低估人为因素和你的程序演变。
编辑:正如ruakh所指出的,实际上有一种方法可以获得s引用,从而安排呼叫。这样,处于热度的开发人员甚至可能不必查看实现您的不间断的类。在我看来,这甚至是实现正确的异常处理的另一个原因。
另一件事:如果你不抛出一个,在超出的级别上记录这样的事件可能是一个不错的选择。InterruptedExceptionThreadThread.interrupt()ThreadExceptionINFO


答案 2

而不是吞下它,如果你如此确定它永远不会发生,你可以崩溃而不是忽略它。例如,抛出一个(或一个):ErrorRuntimeException

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    throw new Error(e);
}

来自 Javadocs for Error

Error 是 Throwable 的一个子类,它指示合理的应用程序不应尝试捕获的严重问题。大多数此类错误都是异常情况。

如果你认为值得假设某件事永远不会发生,那么如果它确实发生了,那就是一种“异常情况”,谁知道呢,可能只是一个“严重的问题”。

另一种看待这个问题的方法是,如果将来有人打断了你的方法,他们是否有可能希望它继续运行,就好像什么都没发生过一样?我猜不会。

推迟

另一种选择是推迟,例如:

try {
    Thread.sleep(1000);
} catch (InterruptedException ignored) {
    Thread.currentThread().interrupt();
}

// ... do some work ...

if (Thread.currentThread().isInterrupted()) {
    // Handle if possible, and was expected,
    // else, throw new `InterruptedException`.
}

请注意,上面的示例代码执行“”,因为这会清除线程的中断标志(这是一个糟糕的模式)。if (Thread.interrupted()) {


推荐