短版:
这是一个已知的最佳实践,永远不要
使用 Thread.interrupt()?
没有。
你能提供
证明它为什么坏了/马车,
并且不应该用于写作
健壮的多线程代码?
情况正好相反:它对多线程代码至关重要。
有关示例,请参见 Java Concurrency in Practice 中的清单 7.7。
加长版:
在这里,我们在一个特定的地方使用这种方法:处理InterruptedExceptions。这可能看起来有点奇怪,但这是代码中的样子:
try {
// Some code that might throw an InterruptedException.
// Using sleep as an example
Thread.sleep(10000);
} catch (InterruptedException ie) {
System.err.println("Interrupted in our long run. Stopping.");
Thread.currentThread().interrupt();
}
这为我们做了两件事:
- 避免吃掉中断异常。 IDE 自动异常处理程序始终为您提供
ie.printStackTrace(); 之类的内容和轻松愉快的“TODO:这里需要一些有用的东西!”评论。
- 它恢复中断状态,而不在此方法上强制检查异常。如果您正在实施的方法签名没有
throws InterruptedException 子句,这是您传播该中断状态的另一种选择。
一位评论者建议我应该使用未经检查的异常“强制线程终止”。这是假设我事先知道突然终止线程是正确的做法。我不。
在上面引用的列表之前的页面上引用 JCIP 的 Brian Goetz:
一个任务不应该假设任何关于它的中断策略
执行线程,除非它被明确设计为在
具有特定中断策略的服务。
例如,假设我是这样做的:
} catch (InterruptedException ie) {
System.err.println("Interrupted in our long run. Stopping.");
// The following is very rude.
throw new RuntimeException("I think the thread should die immediately", ie);
}
我要声明的是,不管调用堆栈的其余部分和相关状态的其他义务如何,这个线程现在需要终止。我会试图偷偷溜过所有其他 catch 块和状态清理代码以直接导致线程死亡。更糟糕的是,我会消耗线程的中断状态。上游逻辑现在必须解构我的异常,以试图弄清楚是否存在程序逻辑错误,或者我是否试图将已检查的异常隐藏在一个模糊的包装器中。
例如,团队中的其他人必须立即执行以下操作:
try {
callBobsCode();
} catch (RuntimeException e) { // Because Bob is a jerk
if (e.getCause() instanceOf InterruptedException) {
// Man, what is that guy's problem?
interruptCleanlyAndPreserveState();
// Restoring the interrupt status
Thread.currentThread().interrupt();
}
}
中断状态比任何特定的InterruptException 更重要。有关具体原因,请参阅Thread.interrupt() 的 javadoc:
如果该线程在调用 wait()、wait(long) 时被阻塞,
或 Object 类或 join() 的 wait(long, int) 方法,
join(long)、join(long, int)、sleep(long) 或 sleep(long, int)、方法
这个类,那么它的中断状态将被清除,它会
收到一个 InterruptedException。
如您所见,在处理中断请求时可以创建和处理多个 InterruptedException,但前提是保留该中断状态。