tl;博士; Future.cancel(false)
仅对避免启动尚未启动的任务有用。
关于并发和取消,有两件重要的事情需要了解。
首先是在 Java 中取消是纯粹的合作。Java 通过让阻塞方法抛出 InterruptedExcetions 并在线程上设置一个标志来发出取消请求的信号。任务实现负责通知取消请求并自行取消。Brian Goetz 在他的处理 InterruptedException的帖子中解释了中断。并非所有任务实现都能正确处理中断。
第二点要指出的是,Future 对象是将来要执行的任务结果的占位符。如果您没有运行很多线程,则任务可能会立即开始执行,但也可能所有线程都已被使用并且任务必须等待。仅仅因为你有一个 Future 对象的引用并不意味着相应的任务实际上已经开始运行。它有点像预订。
您有一个 Future 对象,但任务可能处于以下状态之一:
- 等待。例如,它可能在等待处理器时间的其他任务队列中。
- 跑步。
- 完全的。
如果您的任务处于“等待”的第一个状态,那么两者Future.cancel(true)
都会Future.cancel(false)
将未来标记为已取消。该任务保留在要执行的任务队列中,但是当执行程序到达该任务时,它会注意到已取消的标志并跳过它。
如果您的任务处于第三种状态“已完成”而不是两者Future.cancel(true)
并Future.cancel(false)
返回 false 并且不执行任何操作。这是有道理的,因为它们已经完成并且没有办法撤消它们。
仅当您的任务处于第二个状态“正在运行”时,该mayInterruptIfRunning
标志才重要。
如果您的任务正在运行并且mayInterruptIfRunning
为假,则执行程序不会执行任何操作并允许任务完成。
如果您的任务正在运行并且mayInterruptIfRunning
为真,那么执行程序将中断该任务。但是请记住关于合作取消的一点——为了工作中断,必须实施任务来处理取消。
概括:
Future.cancel(true)
适用于以下情况:
- Future 代表一个长期运行的任务,已知该任务已被实施以处理中断。
Future.cancel(false)
将是正确的:
- 任务实现无法处理被中断。
- 任务实现是否支持取消是未知的。
- 您愿意等待已经开始的任务完成。