[英]Use case for Future.cancel(false)?
In what situation would one want to pass false
for the mayInterruptIfRunning
parameter to Future.cancel()
? 在什么情况下,想要将
mayInterruptIfRunning
参数的false
传递给Future.cancel()
?
If I understand correctly, if you pass false
and the task is cancelled but the thread is not interrupted, the result (or ExecutionException
) will never be accessible because the task is still marked as cancelled (ie isCancelled()
returns true
and get()
throws CancellationException
.) 如果我理解正确,如果您传递
false
并且任务被取消但线程没有被中断,则结果(或ExecutionException
)将永远不可访问,因为任务仍被标记为已取消(即isCancelled()
返回true
并且get()
抛出CancellationException
。)
Other possible situations are: 其他可能的情况是:
Runnable
or Callable
implementation does not check for interrupts and will run to completion even if you do interrupt it (here the interrupt makes no difference) Runnable
或Callable
实现不检查中断,即使你中断它也会运行完成(这里中断没有区别) cancel()
(again the interrupt makes no difference) cancel()
之前,任务已经完成(再次中断没有区别) try ... finally
for this.) try ... finally
为此。) cancel
at all) cancel
) So when/why would you cancel a task without interrupting it? 那么什么时候/为什么你会在不打断任务的情况下取消任务?
tl;dr; TL;博士;
Future.cancel(false)
is only useful to avoid starting tasks that hadn't already been started. Future.cancel(false)
仅用于避免启动尚未启动的任务。
There are two important things to understand regarding concurrency and cancellation. 有关并发和取消的两个重要事项需要了解。
The first is that in Java cancellation is purely cooperative. 首先是在Java中取消纯粹是合作的。 Java signals the cancellation request by having blocking methods throw InterruptedExcetions and by setting a flag on the Thread.
Java通过阻塞方法抛出InterruptedExcetions并在Thread上设置一个标志来发出取消请求的信号。 The task implementation is responsible for noticing the cancellation request AND cancelling itself.
任务实现负责注意取消请求并取消自身。 Brian Goetz explains interruption in his post Dealing with InterruptedException .
Brian Goetz解释了他在处理InterruptedException的帖子中的中断 。 Not all task implementations will correctly handle interruption.
并非所有任务实现都能正确处理中断。
The second thing to point out is that the Future object is a placeholder for the results from a task to be executed in the future. 要指出的第二件事是Future对象是一个占位符,用于将来要执行的任务的结果。 If you don't have alot of threads running it is possible that the task starts executing right away but its also possible that all the threads are already being used and the task has to wait.
如果你没有很多线程在运行,那么任务可能会立即开始执行,但也可能是所有线程都已被使用而且任务必须等待。 Just because you have a reference to a Future object that doesn't mean that the corresponding task has actually started running.
仅仅因为您对Future对象的引用并不意味着相应的任务实际上已经开始运行。 Its sort of like a reservation.
这有点像预订。
You have a Future object but the task could be in one of the following states: 您有一个Future对象,但该任务可能处于以下状态之一:
If your task is in the first state "Waiting" then both Future.cancel(true)
and Future.cancel(false)
will mark the future as cancelled. 如果您的任务处于第一个状态“Waiting”,那么
Future.cancel(true)
和Future.cancel(false)
都会将未来标记为已取消。 The task remains in the queue of tasks to execute but when the executor gets to the task it notices the cancelled flag and skips it. 任务保留在要执行的任务队列中,但是当执行程序到达任务时,它会注意到已取消的标志并跳过它。
If your task is in the third state "Completed" than both Future.cancel(true)
and Future.cancel(false)
return false and don't do anything. 如果您的任务处于第三个状态“已完成”,则
Future.cancel(true)
和Future.cancel(false)
返回false并且不执行任何操作。 Which makes sense because they are already done and there isn't a way to undo them. 这是有道理的,因为它们已经完成,并且没有办法撤消它们。
The mayInterruptIfRunning
flag is only important if your task is in the second state "Running". 只有当您的任务处于第二个状态“正在运行”时,
mayInterruptIfRunning
标志才有用。
If your task is running and mayInterruptIfRunning
is false then the executor doesn't do anything and allows the task to complete. 如果您的任务正在运行且
mayInterruptIfRunning
为false,则执行程序不会执行任何操作并允许任务完成。
If your task is running and mayInterruptIfRunning
is true then the executor will interrupt the task. 如果您的任务正在运行并且
mayInterruptIfRunning
为true,则执行程序将中断该任务。 But remember the bit about cooperative cancellation - for the interruption to work the task has to have been implemented to handle cancellation. 但请记住关于合作取消的一点 - 为了中断工作,必须实施任务来处理取消。
Summary: 摘要:
Future.cancel(true)
is appropriate when: Future.cancel(true)
适用于:
Future.cancel(false)
would be correct: Future.cancel(false)
是正确的:
If you're afraid interrupting the task's execution might leave things in a bad state, and you simply want to mark it as canceled so that users of the Future
will be aware of it (eg they should know the statistics requested weren't performed on time). 如果您害怕中断任务的执行可能会使事情处于不良状态,并且您只是想将其标记为已取消,以便
Future
用户将意识到它(例如,他们应该知道请求的统计信息未执行时间)。
Writing threaded code that handles interrupts correctly is not trivial at all, and so one might simply prefer to avoid it. 编写正确处理中断的线程代码根本不是微不足道的,因此人们可能更愿意避免它。
Some information can be found here , here and of course in the great book Concurrent Programming in Java (by the guy who originally wrote java.util.concurrent
). 有些信息可以发现在这里 , 在这里 ,当然在大书用Java并发编程 (由谁最初写的家伙
java.util.concurrent
)。
I have a use case that might be interesting to you: I have a single thread that is executing a set of scheduled tasks. 我有一个可能对您感兴趣的用例:我有一个执行一组计划任务的线程。 One of the tasks may be rescheduled by either itself or another task.
其中一项任务可以由其自身或其他任务重新安排。
To do this, I use Future.cancel(false)
on the existing copy in the queue, and then schedule the task for the new time. 为此,我在队列中的现有副本上使用
Future.cancel(false)
,然后为新时间安排任务。
If this code is called from the scheduled task itself, the cancel operation will be a no-op, and the task will be scheduled to run again in the future. 如果从计划任务本身调用此代码,则取消操作将是无操作,并且该任务将被安排在将来再次运行。 If the code is called from another context, the upcoming task hasn't started execution yet, so it will be canceled, and replaced with a task scheduled for the new time.
如果从另一个上下文调用代码,则即将执行的任务尚未开始执行,因此它将被取消,并替换为为新时间安排的任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.