sleep
或其他可中断的方法,如果我知道代码中没有其他人对该线程进行中断,那么忽略InterruptedException是否可以呢?换句话说,如果该线程应该与JVM一起存在,表示该线程不可中断,那么可以安全地假设InterruptedException将永远不会被调用,因此可以吞掉该异常吗?
sleep
或其他可中断的方法,如果我知道代码中没有其他人对该线程进行中断,那么忽略InterruptedException是否可以呢?try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
在我看来,这是InterruptedException
的最小捕获实现。在循环中检查isInterrupted
标志不会带来太多额外开销。与您的未来程序员自己为寻找意外线程行为而烦恼一两天相比,这点开销微不足道,因为您的项目可能已经增长了一些。safeSleep
实用程序方法,该方法负责处理Exception
并正确设置标志。InterruptedException
在硬件故障的情况下JVM本身不会抛出,它只是用户指定的Exception
。那就技术上是这样的。但是,不应低估人为因素和您的程序演变。Thread
的引用,并因此安排Thread.interrupt()
调用。这种方式,发热的开发者甚至可能不必查看实现您不可中断的Thread
的类。在我看来,这甚至是实现适当异常处理的另一个理由。另一件事:如果您不抛出异常,那么将此类事件记录在高于INFO
级别的日志中可能是一个不错的选择。Thread
的引用,就不会有其他Thread
能够调用它的Thread.interrupt()
方法。”线程不像随意的对象,您可以决定是否传播。JDK提供了查找所有线程的方法。请参见https://dev59.com/TXM_5IYBdhLWcg3wjkCr,了解一些方法。 - ruakhsafeSleep
方法:你可以使用 Guava 的 Uninterruptibles
(例如 Uninterruptibles.sleepUninterruptibly
)而不是自己实现。 - randers如果你确信某件事永远不会发生,那么与其忽略它,不如选择崩溃。比如,抛出一个Error
(或者RuntimeException
):
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new Error(e);
}
从Error的Javadocs中得知:
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()) {
",因为那会清除线程的中断标记(这是一个不好的模式)。
AssertionError
жқҘеӨ„зҗҶиҝҷдёӘй—®йўҳпјҢдёҚиҝҮиҝҷеҸӘжҳҜдёӘдәәеҒҸеҘҪгҖӮ - user253751InterruptedException
,就直接抛出 InterruptedException
本身。对于库代码来说尤其如此。如果这是你的应用程序代码,无论你是重新抛出还是忽略异常,实际上都不会有任何区别,因为你可以保证它根本不是在第一次引起的。另一个选择是优雅地退出你的线程。 - DorusRunnable.run()
抛出InterruptedException
。如果你的意思是“在某个方法内抛出InterruptedException
,然后调用该方法”,那么当调用它的线程发生什么情况时,你会怎么做呢? - Dan Getz如果您认为异常不应该发生,那么就不要将其吞咽。可以决定不添加处理永远不会发生的条件的代码,但不应该默默无闻地发生异常。
你至少应该做到:
catch(InterruptedException ex) {
throw new AssertionError(ex);
}
这样可以确保只要您断言“这永远不会发生”的错误,就会注意到。该模式还适用于其他意外异常,例如当您知道目标OutputStream
是ByteArrayOutputStream
或Formatter
的Appendable
应该是StringBuilder
等,并出现IOException
。
顺便说一下,有一种替代方法可以完全不需要处理InterruptedException
,即:Thread.sleep
。
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));
当线程被中断时,此方法将简单地返回早期,并保留Thread
的中断状态,因此对于使用中断的其他人使用代码的情况(假设调用者检查了中断状态),它已经提供了正确的处理方式。
LockSupport
- 你让我今天又学会了 Java 中不太常见的特性... - user719662我依然认为Goetz等人的《Java并发编程实践》是这些问题的圣经,在第七章中提到了以下重要内容(Goetz的developerWorks文章基本上涵盖了相同的材料,但书中在一些方面更加清晰明了)。
中断是一种合作机制。一个线程不能强制另一个停止正在做的事情并去做其他事情;当线程A中断线程B时,只是请求B在方便的停止点停下它正在做的事情 - 如果它觉得需要停下来的话。
[...]
只有实现线程中断策略的代码才能吞噬中断请求。通用任务和库代码不应该吞噬中断请求。
所以,在你概述的情况下,你可以“吞掉” InterruptedException
异常。
此外,书中还有一个重要的观点:
所以你可以选择自己的策略,比如使用由于每个线程都有自己的中断策略,除非你知道中断对该线程意味着什么,否则不应该中断线程。
RuntimeException
、AssertionError
来“崩溃”,只将其记录为警告,或完全忽略中断,只要你为其他需要知道此问题的人记录下来。最好的选择取决于你的线程实际在做什么,而你没有提供相关细节信息。例如,如果它正在火箭上运行[比如进行姿态控制],你不想因某个同事程序员[他可能甚至不是你们公司的人,例如他编写了一个库供你调用]在他的代码中忘记了某个合同并在你的代码上产生了一个安全可忽略的异常而导致JVM/火箭崩溃:“所发生的异常不是由于随机故障引起的,而是由于设计错误引起的。”这个问题不能忽略。在抛出InterruptedException
时,要么将其返回给调用者,要么重新断言线程的中断状态,因为静态状态会在抛出异常后被清除:
} catch (InterruptedException e) {
// Restores the interrupted flag status.
Thread.currentThread().interrupt();
}
除非你在捕获异常后立即退出线程。
这里是一篇关于处理InterruptedException
的文章。
InterruptedException
仅从阻塞方法(如Thread.sleep(...)
)抛出,而从正常代码行中永远不会抛出,
程序员需要决定线程如何响应中断。
例如,有一个项目只是对它进行了文档描述:
public class MyTask {
// ...
/**
* Waits for result to be use ready.
* <br>
* <br>
* <b>Warning:</b> instead of throwing {@link InterruptedException},
* returns {@code null}, and if that is undesired, do something like:
*
* <pre>{@code
* MyResult result = myTask.await(...);
* if (Thread.currentThread().isInterrupted()) {
* throw new InterruptedException();
* }
* }</pre>
*
* @param timeout Duration to wait at most.
* @param unit Type of duration.
*/
public MyResult await(long timeout, TimeUnit unit) {
try {
return /* ... */;
} catch (InterruptedException e) {
// Restores the interrupted flag status.
Thread.currentThread().interrupt();
}
return null;
}
}
if (Thread.interrupted()) {
,因为这会清除线程上的中断标志(这是一种不好的模式)。如果您的项目变得越来越复杂,那么很难肯定没有人会调用中断方法。如果有一天有人调用此方法并发生InterruptedException,那么如果您没有至少在某个地方记录它,将会非常难以调试。
InterruptedException
永远不会被抛出,因此异常可以被吞咽。如果您要吞掉异常的代码完全在您的控制下,并且如果它只是客户端代码(它永远不会在您自己以外的上下文中重用),那么可以安全地吞掉异常。请注意,这里有很多如果。如果您恰好使用Java 8,则有另一种选择,在这里描述:将您的代码包装在一个uncheckCall(() -> { ... })
块中。这使得代码块可以抛出InterruptedException
而不声明它。如链接答案所述,这应该非常小心地处理,但它有潜力使您的代码非常干净。
Thread.interrupt()
等)产生中断的情况下抛出InterruptedException? - MinecraftShamrock^C
停止程序时,Maven会出现问题。 - nanofarad