Future.cancel(false)的用例?

2022-09-03 00:27:56

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

如果我理解正确,如果您通过并且任务被取消但线程中断,则结果(或)将永远无法访问,因为任务仍标记为已取消(即 返回和抛出 。falseExecutionExceptionisCancelled()trueget()CancellationException

其他可能的情况包括:

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

那么,您何时/为什么要在不中断任务的情况下取消任务呢?


答案 1

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

关于并发性和取消,有两件重要的事情需要了解。

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

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

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

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

如果您的任务处于第一个状态“正在等待”,则两者都将和将未来标记为已取消。任务保留在要执行的任务队列中,但当执行程序到达任务时,它会注意到已取消的标志并跳过它。Future.cancel(true)Future.cancel(false)

如果你的任务处于第三种状态“已完成”,则两者都返回 false 并且不执行任何操作。这是有道理的,因为它们已经完成了,没有办法撤消它们。Future.cancel(true)Future.cancel(false)

仅当任务处于第二种状态“正在运行”时,该标志才重要。mayInterruptIfRunning

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

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

总结:

Future.cancel(true)适用于以下情况:

  1. “未来”表示一个长期运行的任务,已知已实现该任务以处理中断。

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

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

答案 2

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

编写正确处理中断的线程代码并非易事,因此人们可能只是希望避免它。

一些信息可以在这里找到,在这里,当然还有伟大的书《Java中的并发编程》(由最初编写的人撰写)。java.util.concurrent


推荐