我有一个长期运行的任务,是这样的:

public void myCancellableTask() {
    while ( someCondition ) {
       checkIfCancelRequested();
       doSomeWork();
    }
 }

在任务可以被取消(取消请求和checkIfCancelRequested()检查取消标志)。通常,当我写撤销的循环就是这样,我用一个标志,表示取消已请求。但是,我知道我还可以使用了Thread.interrupt并检查线程已经中断。我不知道这将是首选的方法,为什么,想法?

感谢,

杰夫

有帮助吗?

解决方案

中断将爆螺纹出的指定的等待条件的列表的。你自己的取消标志不会。如果你想中断对IO和事件的等待,使用中断。否则,使用你自己的。

其他提示

使用中断的一个问题是,如果你不控制正在执行的所有代码的,你运行中断的风险,不是因为别人的如何破理解工作“正常”处理中断在其库中。这是API的无形的出口的API围绕其处理您变得依赖于interrupts的。

在您的例子,假设doSomeWork是第三方JAR,看起来像:

public void doSomeWork() {
    try { 
        api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); }
}

现在你必须处理的AssertionError(或任何你正在使用可能会引发库)。我见过有经验的开发扔各种各样的废话在接收中断!在另一方面,也许方法是这样的:

public void doSomeWork() {
    while (true) {
        try { 
            return api.callAndWaitAnswer() ; 
        } 
        catch (InterruptedException e) { /* retry! */ }
    }
}

这“不当处理”的中断导致程序无限循环。再次,不排除这是荒谬的;有很多的破碎的中断处理机制在那里。

至少使用自己的标志将是任何第三方库完全不可见。

这取决于doSomeWork()实现。那是纯粹的计算或做它(在任何时候),涉及阻塞API(如IO)电话?每 bmargulies的的答案,在JDK许多阻塞的API中断,并会传播中断异常堆栈。

因此,如果工作需要可能阻塞的活动,则need'll采取中断考虑即使你决定使用标志来控制的过程中,并应适当地捕获并处理的 /传播中断。

除此之外,如果依靠一个标志,请确保您的标志都被定义为volatile语义。

我认为这是优先在大多数情况下的问题。 我个人会去手工制作的标志。它给你更多的控制 - 例如,这样你确保你的线程不会留下其他对象处于不一致的状态。 此外,如果性能是真正的关键,记住,使用异常有开销(即使是在可以忽略不计的情况下,99%)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top