Java长时间运行任务线程中断vs取消标志

Jef*_*rey 14 java concurrency multithreading interrupt

我有一个长期运行的任务,如:

public void myCancellableTask() {
    while ( someCondition ) {
       checkIfCancelRequested();
       doSomeWork();
    }
 }
Run Code Online (Sandbox Code Playgroud)

任务可以取消(请求取消,checkIfCancelRequested()检查取消标志).通常,当我编写这样的可取消循环时,我使用一个标志来指示已请求取消.但是,我知道我也可以使用Thread.interrupt并检查线程是否被中断.我不确定哪种方法是首选,为什么,想法?

谢谢,

杰夫

oxb*_*kes 21

使用中断的一个问题是,如果你不控制所有正在执行的代码,你就会冒中断不能正常工作的风险,因为别人对如何处理库中的中断有了深刻的理解.这就是API 无形地导出一个API来处理interrupt你所依赖的s.

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

public void doSomeWork() {
    try { 
        api.callAndWaitAnswer() ; 
    } 
    catch (InterruptedException e) { throw new AssertionError(); }
}
Run Code Online (Sandbox Code Playgroud)

现在你必须处理一个AssertionError(或者你正在使用的任何其他库可能会抛出).我见过有经验的开发人员在收到中断时会抛出各种废话!另一方面,也许方法看起来像这样:

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

这种"不正确的中断处理"会导致程序无限循环.再次,不要认为这是荒谬的; 那里有很多破坏的中断处理机制.

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


bma*_*ies 6

中断将使线程从指定的等待条件列表中爆炸出来.你自己的取消标志不会.如果要中断IO和事件的等待,请使用中断.否则使用自己的.