Thread.interrupt()是邪恶的吗?

rip*_*234 30 java multithreading interrupt

一位队友提出以下要求:

" Thread.interrupt()本质上是破碎的,应该(几乎)永远不会被使用".

我试图理解为什么会这样.

它是一个永远不会使用的已知最佳实践Thread.interrupt()吗?你能提供证据证明它为何被破坏/错误,并且不应该用于编写强大的多线程代码吗?

注意 - 如果从设计防腐剂中"非常",我对这个问题不感兴趣.我的问题是 - 它有多少?

Bob*_*oss 40

精简版:

它是一个已知的最佳实践永远不会使用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();
}
Run Code Online (Sandbox Code Playgroud)

这对我们来说有两件事:

  1. 它避免吃掉中断异常.IDE自动异常处理程序总能为您提供类似的东西ie.printStackTrace();以及轻松的"TODO:有用的东西需要去这里!" 评论.
  2. 它会恢复中断状态,而不会在此方法上强制执行检查异常.如果您正在实现的方法签名没有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);
}
Run Code Online (Sandbox Code Playgroud)

我将声明,无论其他调用堆栈和相关状态的其他义务如何,此线程现在都需要死亡.我会试图偷偷过去所有其他的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

中断状态比任何特定状态更重要InterruptException.有关具体示例的原因,请参阅Thread.interrupt()的javadoc :

如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long,int)方法中阻塞了这个线程,sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException.

如您所见,在处理中断请求时,可以创建和处理多个InterruptedException,但仅限于保留该中断状态.

  • @Will,重点是:我接受中断,然后强制中断继续.如果我只是在方法上有一个"抛出InterruptedException"子句,任何拥有"catch(Exception e){}"块的人都会吃掉异常.睡眠在控件C上被中断:如果你吃了异常,你的线程就不会停止. (3认同)

Sbo*_*odd 16

我知道它Thread.interrupt()破坏的唯一方法是它实际上并没有像它看起来那样 - 它实际上只能中断侦听它的代码.

但是,正确使用,在我看来,它似乎是一个很好的内置机制,用于任务管理和取消.

我推荐Java Concurrency in Practice,以便更好地阅读它的正确和安全使用.


Aar*_*lla 11

主要问题Thread.interrupt()是大多数程序员不知道隐藏的陷阱并以错误的方式使用它.例如,当您处理中断时,有一些方法可以清除标志(因此状态会丢失).

此外,调用不会立即中断线程.例如,当它在一些系统例程中挂起时,什么都不会发生.实际上,如果线程没有检查标志并且从不调用抛出的Java方法InterruptException,那么中断它将不会产生任何影响.