2016-05-15 75 views
3

Java并发,实际上,国家在以下几点:理解中断取消与未来

线程只能由其所有者中断;车主可以 封装在一个 适当的取消机制线程的中断政策的知识,如关机方法现在

让我们来看看标准FutureTask实现:

public boolean cancel(boolean mayInterruptIfRunning){ 

    //... 
    if (mayInterruptIfRunning) { 
     try { 
      Thread t = runner; 
      if (t != null) 
       t.interrupt(); //Future task may not be an owner, 
           //yet it interrupts the running thread. 
     } 
    //... 
    } 
    //... 
} 

那么,为什么它安全?在ThreadPoolExecutor情况下,这newTaskFor的实现只是

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { 
    return new FutureTask<T>(runnable, value); 
} 

它是安全的调用是这样的:

ExecutorService es; 
Callable<Integer> task; 
//init es, task 
Future<Integer> ft = es.submit(task); 
ft.cancel(true); //Attention at this line, thread may be interrupted 

ThreadPoolExecutor情况下,我们不知道有关线程中断的政策,无论是FutureTask。不过,我们通过FutureTask来打断它。这是一种令人困惑的...

回答

1

没有声称它是“安全的”。措辞是“一个线程应该只能被其所有者中断”,而不是必须

如果你打电话给cancel(true),那么你应该准备好任何中断线程的效果。

+0

但中断是专门为取消活动而设计的机制。对于'ExecutorService',我们最好不要对它的线程中断策略做任何假设,我想......但是如果我们在由'ExecutorService'生成的'Future'上调用'cancel(true)',我们实际上会所以。否则,一项任务(即使是可重复中断的任务)也不会被“中断”并被允许完成。这种“取消”似乎对我来说完全没有意义。 – user3663882

+0

我咨询了ThreadPoolExecutor :: shutdownNow()的来源。很明显,它会中断所有工作线程。 – user3663882

1

本书引用的是其作者对最佳实践的看法,而不是关于线程安全的声明。不幸的是,这本书没有清楚地区分两种类型的陈述。

1

首先,让我们确保问题是合法的。从书中引用:

因为每个线程都有自己的中断策略,所以除非知道该线程的中断意味着什么,否则不应该中断线程。

是否FutureTask中断底层线程是由mayInterruptIfRunning参数控制的。因此FutureTask不决定何时中断该线程,调用者决定。因为她控制执行服务,因此调用者应该了解什么是中断策略。

另一方面,ThreadPoolExecutor并没有真正记录中断其线程的合同(cancels tasks via Thread#interruptshutdownNow()除外),因此在调用方中强加原则违规。我想合同可以在这方面得到改善。不过,它的行为很自然。使用中断标志是如何让正在执行的任务知道取消的最简单方法(否则可能需要将可查询状态的对象传递给任务,这很麻烦)。

那么,它为什么安全?

在这种情况下,ThreadPoolExecutor并不在乎我们是否中断线程。只有内部运行的任务可能在意,而且这些任务由来电者控制。 ThreadPoolExecutor确保的唯一两件事情是在新任务启动之前中断标志被清除,并且线程在关闭时被中断(因为执行者拥有线程,这并不违反原则)。