如果没有人调用interrupt(),可以忽略InterruptedException吗?
如果我创build自己的线程(即不是线程池)和某处我调用sleep
或任何其他可中断的方法,可以忽略InterruptedException, 如果我知道代码中没有其他人正在线程上执行中断 。
换句话说,如果线程应该和JVM一样长,意味着线程不可中断,那么假设InterruptedException 永远不会被调用,因此可以吞噬exception呢?
忽略检查的exception从来没有被认为是安全的。
你现在可能没关系,但是如果另一个程序员扩展了你的代码,他会期待标准的行为:线程响应中断调用。
另外一个空的catch块在这种情况下是危险的,因为JVM删除中断的标志,并且应该再次设置
Thread.currentThread().interrupt();
在catch块。 在我看来,这是InterruptedException
s的最小捕获实现。 在循环中检查isInterrupted
标志也不会太大伤害。
与您未来的程序员自己的麻烦相比,这是一个小的开销,因为您的项目可能已经长大了一点点,所以在一两天内寻找意外的线程行为。
如果您觉得您的代码的可读性受到这些catch实现的影响,那么您可以实现自己的safeSleep
实用程序方法,该方法负责处理Exception
并正确设置标志。
另一方面,在发生硬件故障的情况下,JVM本身不会抛出InterruptedException
, 而只是一个用户指定的Exception
。 所以,如果你不传播你的 这就是技术 。 但是,你不应该低估人的因素和你的计划的演变。 Thread
的引用,那么就不会有其他能够调用Thread.interrupt()
Thread
。
编辑:正如ruakh指出的那样,实际上有一种方法来获得一个Thread
的引用,从而安排一个Thread.interrupt()
调用。 那样的话,开发者可能甚至不需要去看那个实现了不间断Thread
。 在我看来,这是另一个原因,要实施适当的exception处理。
另一件事 :如果你不抛出一个Exception
,在INFO
以外的级别上logging这样的事件可能是一个不错的select。
如果你确信它永远不会发生,你可以崩溃而不是忽略它,而不是吞下去。 例如,抛出一个Error
(或一个RuntimeException
):
try { Thread.sleep(1000); } catch (InterruptedException e) { throw new Error(e); }
从Javadocs错误 :
一个错误是Throwable的一个子类,表示一个合理的应用程序不应该试图捕捉的严重问题。 大多数这样的错误是exception的条件
如果你认为值得假设的事情是永远不会发生的,那么如果真的发生了,那么这是一个“exception情况”,谁知道这可能只是一个“严重的问题”。
另一种看待这个问题的方法是,如果将来某个人打断了你的方法,他们是否有希望继续运行,就好像什么都没有发生过一样? 我猜不。
如果您认为永远不会发生exception,则永远不要吞下exception。 可以决定不添加代码处理一个永远不会发生的情况,但不应该默默地发生。
你应该做的最低限度是:
catch(InterruptedException ex) { throw new AssertionError(ex); }
这确保了每当你断言永远不会发生错误,你会注意到。 这种模式也适用于其他意想不到的exception,例如,当你知道目标OutputStream
是ByteArrayOutputStream
或者Formatter
的Appendable
应该是一个StringBuilder
, IOException
等。
顺便说一句,有一个Thread.sleep
的替代方法,根本不需要处理InterruptedException
:
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));
这个方法只会在线程被中断的时候提前返回,并且保持线程的中断状态,所以它提供了一个正确的处理方式,以便别人使用中断来使用你的代码(假设你的代码的调用者然后检查中断状态)。
这本书,我仍然认为这些问题的圣经,戈茨等人。 实践中的Java Concurrency指出了第7章中的以下重要部分(在Goetz的developerWorks文章中提供了相同的材料,这些材料具有免费的优势,但是在某些方面,本书有点更清晰)。
中断是一个合作机制。 一个线程不能强迫另一个线程停止正在做的事情并做其他事情; 当线程A中断线程B时,A仅仅是要求B停止它在到达一个方便的停止点时正在做的事情 – 如果它感觉的话。
[…]
只有实现线程中断策略的代码才能吞下中断请求。 通用任务和库代码不应该吞下中断请求。
所以,是的,在您列出的情况下,您可以“吞下” InterruptedException
。
这本书中的重要一点:
由于每个线程都有自己的中断策略,因此除非知道该线程的中断意味着什么,否则不应该中断线程。
所以你可以select你自己的策略,像RuntimeException
, AssertionError
“崩溃”,只要把它作为一个警告logging下来,或者完全忽略中断,只要你把这个问题logging给其他任何可能需要知道的人。 什么是最好的取决于你的线程是真的在做什么,你没有提供任何细节。 例如,如果它运行在一个火箭上(说做态度控制),那么你不想因为一个程序员(他甚至可能不像你一样为同一个公司工作,就像他写了一些库电话]忘记了他的代码中的某个合同,并且抛弃了一个安全可以忽略的exception: “发生的exception不是由于随机故障,而是devise错误。
如果你的项目变得越来越复杂,越来越难说,绝对没有人会叫中断方法。 如果某个人有一天会调用这个方法,并且发生一个InterruptedException,那么如果你至less没有把它logging到某个地方,就很难debugging这个方法。
这不应该被忽视。 它应该被抛回给调用者,或者你应该重新抛出抛出exception时被清除的线程中断状态:
catch (InterruptedException e) { // Restore the interrupted status Thread.currentThread().interrupt(); }
除非你在抓住后立即退出线程。
这里有一篇关于处理InterruptedException
的文章。
如果线程应该和JVM一样长,意味着线程不可中断,那么假设
InterruptedException
永远不会被抛出,因此可以吞噬exception吗?
我明白你的痛苦,没有任何商业价值的试用版模块的泛滥会伤害代码。
如果您打算吞下exception的代码完全在您的控制之下,并且如果它只是客户端代码 (它不会在您自己的上下文中被重用),那么吞下exception是安全的。 请注意,有很多如果在那里。
如果您恰好使用Java 8,则可以使用另一个选项,如下所述:将代码包装在uncheckCall(() -> { ... })
块中。 这让代码块抛出InterruptedException
而不声明它。 正如在链接的答案中所解释的,这应该非常谨慎地处理,但是它有可能使您的代码非常干净。
我认为,忽略InterruptedException是否安全,取决于你在那个线程中做什么。 如果有任何情况下,不必要的中断到您的线程可以离开系统或任何资源处于不需要的状态(脏,locking,不释放,这可能会导致泄漏资源),那么它负责处理InterruptedException,你不应该忽略它。 是否要让你的线程可以中断,取决于你。
换句话说,中断机制主要用于执行取消策略和任务清理。 你没有任何清理任务,或者你没有任何具体的任务取消政策,忽略IntrruptedException可能听起来不符合政治正确,但是没问题。