Learn to cancel a task submitted to an executor service if the task still has to be executed and/or has not been completed yet. We can use the cancel()
method of Future
object that allows making the cancellation requests.
1. Future cancel() API
The Future.cancel() method takes one argument of type boolean
.
boolean cancel(boolean mayInterruptIfRunning);
Depending on the value of mayInterruptIfRunning
and the status of the task submitted to the executor, the behavior of this method is different:
- If the task has been completed or has been canceled earlier, or it can’t be cancelled due to any other reason, the method will return the
false
value and the task won’t be canceled. - If the task is waiting in the queue to begin execution, the task will be canceled and will never begin its execution. The method will return
true
. - If the task is already running and the value of
mayInterruptIfRunning
the parameter istrue
, InterruptedException is sent to the thread in an attempt to stop the task. Therefore, task must periodically check for interrupt status and stop working if it is true. - If the task is already running and the value of
mayInterruptIfRunning
the parameter isfalse
, the thread will NOT be interrupted.
2. Cancelling a Task in Waiting Queue
In this example, we have a task that will be executed after a minute from the scheduled time. After scheduling, we check the status of the task using isDone() method, which returns false
because the task is not completed yet.
Then we cancel the task and check the status of the task using isCancelled()
and isDone()
methods, both.
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class CancelATask { public static void main(String[] args) { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); ScheduledFuture<?> future = executor .schedule(() -> { System.out.println("Some Task"); }, 5, TimeUnit.SECONDS); System.out.println("Before Cancel - Task is done : " + future.isDone()); System.out.println("Before Cancel - Task is cancel : " + future.isCancelled()); if (future.isDone() == false) { future.cancel(false); } System.out.println("Before Cancel - Task is done : " + future.isDone()); System.out.println("Before Cancel - Task is cancel : " + future.isCancelled()); executor.shutdown(); } }
Program output.
Before Cancel - Task is done : false Before Cancel - Task is cancel : false Task is cancelled : true Task is done : true
3. Cancelling a Task in Execution
If the task has already started execution, then we cannot stop its execution, normally. We must interrupt the thread and let the task stop itself.
future.cancel(true)
An example of handling the interrupt inside the thread is as follows. Use this code in the task to check the interrupt status periodically.
if (Thread.interrupted()) { throw new InterruptedException(); }
Finally, cancel the task execution by returning from the thread.
try { //task code } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; }
Leave a Reply