Future.cancel的用例(false)?

fin*_*nnw 13 java concurrency future

在什么情况下,人们想要falsemayInterruptIfRunning参数传递给Future.cancel()

如果我理解正确,如果你通过false并且任务被取消但是线程没有被中断,那么结果(或ExecutionException)永远不会被访问,因为任务仍被标记为已取消(即isCancelled()返回trueget()抛出)CancellationException.

其他可能的情况是:

  • RunnableCallable执行不检查中断和将运行完,即使你打断它(这里的中断没有区别)
  • 在您调用之前任务已经完成cancel()(再次中断没有区别)
  • 任务需要在退出之前执行一些清理(一个编写良好的实现将try ... finally用于此.)
  • 任务无法立即终止,必须继续执行受中断影响的操作,例如阻塞I/O(在这种情况下,您可能根本不应该调用cancel)

那么什么时候/为什么你会在不打断任务的情况下取消任务?

Rya*_*yan 11

TL;博士; Future.cancel(false)仅用于避免启动尚未启动的任务.

有关并发和取消的两个重要事项需要了解.

首先是在Java中取消纯粹是合作的.Java通过阻塞方法抛出InterruptedExcetions并在Thread上设置一个标志来发出取消请求的信号.任务实现负责注意取消请求并取消自身.Brian Goetz解释了他在处理InterruptedException的帖子中的中断.并非所有任务实现都能正确处理中断.

要指出的第二件事是Future对象是一个占位符,用于将来要执行的任务的结果.如果你没有很多线程在运行,那么任务可能会立即开始执行,但也可能是所有线程都已被使用而且任务必须等待.仅仅因为您对Future对象的引用并不意味着相应的任务实际上已经开始运行.这有点像预订.

您有一个Future对象,但该任务可能处于以下状态之一:

  1. 等候.例如,它可能在等待处理器时间的其他任务的队列中.
  2. 运行.
  3. 已完成.

如果你的任务是在第一状态"等待",则既Future.cancel(true)Future.cancel(false)将标志着作为未来取消.任务保留在要执行的任务队列中,但是当执行程序到达任务时,它会注意到已取消的标志并跳过它.

如果您的任务处于第三个状态"已完成"而不是两个Future.cancel(true)Future.cancel(false)返回false并且不执行任何操作.这是有道理的,因为它们已经完成,并且没有办法撤消它们.

mayInterruptIfRunning只有当您的任务处于第二个状态"正在运行"时,该标志才有用.

如果您的任务正在运行且mayInterruptIfRunning为false,则执行程序不会执行任何操作并允许任务完成.

如果您的任务正在运行且mayInterruptIfRunning为true,则执行程序将中断该任务.但请记住关于合作取消的一点 - 为了中断工作,必须实施任务来处理取消.

摘要:

Future.cancel(true) 适合的时候:

  1. Future代表了一个长期运行的任务,已知它已经被实现来处理中断.

Future.cancel(false) 这是正确的:

  1. 任务实现无法处理被中断.
  2. 如果任务实现支持取消,它是未知的.
  3. 您愿意等待已经开始的任务完成.


aby*_*byx 8

如果您害怕中断任务的执行可能会使事情处于不良状态,并且您只是想将其标记为已取消,以便该用户Future将意识到它(例如,他们应该知道所请求的统计信息未按时执行).

编写正确处理中断的线程代码根本不是微不足道的,因此人们可能更愿意避免它.

有些信息可以发现在这里,在这里,当然在大书用Java并发编程(由谁最初写的家伙java.util.concurrent).