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

我有一个长时间运行的任务,比如:

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

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

谢谢

杰夫


答案 1

使用中断的一个问题是,如果您不控制正在执行的所有代码,则可能会遇到中断无法“正常工作”的风险,因为其他人对如何处理其库中的中断的理解是错误的。也就是说,API 在无形中导出 API,围绕其对你所依赖的 s 的处理。interrupt

在您的示例中,假设在第三方 JAR 中,如下所示:doSomeWork

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! */ }
    }
}

这种对中断的“不正确处理”会导致程序无限期地循环。同样,不要认为这是荒谬的;有很多破碎的中断处理机制。

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


答案 2

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


推荐