1. Future cancel() API

The Future.cancel() method takes one argument of typeboolean

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 is true, Interrupted Exception 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 is false, 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();
  }
}

Output:

Before Cancel - Task is done : false
Before Cancel - Task is cancel : false

Task is cancelled : true
Task is done : true

Clearly, after the task is canceled, the done status of the task is also 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;
}

4. Conclusion

The Future.cancel() API is very useful in cancelling a task that has either not started yet, or has started but not completed. A completed task can’t be cancelled in any way.

Drop me your questions in the comments regarding how to cancel a task submitted to executor in Java.


Leave a Reply

Your email address will not be published. Required fields are marked *