The scheduledTaskCancellation() method at (13) illustrates how to cancel a submitted task by scheduling a second task to do the cancellation, if necessary. As there are two tasks involved, a scheduled thread pool of size 2 is created at (14). The first task is submitted at (15) to compute the factorial of a big number. A second task is scheduled at (16) to call the cancel() method on the Future<BigInteger> object representing the first task, after a delay of 10 milliseconds. If the first task has completed before the cancel() method is called, it has no effect on the first task. However, if the first task has not completed execution before the second task executes, the cancel() method will send an interrupt signal to the thread of the first task in an attempt to stop it. The output from the program shows that the first task was interrupted by the scheduled task. The isCancelled() method called on the Future<BigInteger> object at (18) confirms that the task was indeed cancelled. The output in this case depends on the execution time to compute the factorial for the specified number at (15) and the delay specified in the schedule() method at (16), before the call to the cancel() method is executed.

In summary, task cancellation is dependent on exploiting the thread interrupt system and providing an appropriate action in the interrupted thread executing the task.

Example 23.5 Task Cancellation

Click here to view code image

package executors;
import java.math.BigInteger;
import java.util.concurrent.*;
public class TaskCancellation {
  // Computation-intensive task:
  private static BigInteger bigFactorial(int number) {                    // (1)
    String threadName = Thread.currentThread().getName();
    BigInteger factorial = BigInteger.ONE;
    try {
      for (int i = 2; i <= number; i++) {
        factorial = factorial.multiply(BigInteger.valueOf(i));
        if (Thread.interrupted()) {                                       // (2)
          throw new InterruptedException();
        }
      }
      System.out.println(threadName + ” completed.”);
    } catch (InterruptedException e) {
      System.out.println(threadName + ” interrupted.”);                   // (3)
    }
    return factorial;
  }
  private static void timedTaskCancellation() {                           // (4)
    System.out.println(“Timed task cancellation:”);
    int number = 100000;
    long timeout = 1;
    TimeUnit unit = TimeUnit.SECONDS;
    System.out.println(“NUMBER: ” + number + “, “
                     + “TIMEOUT: ” + timeout + ” ” + unit);
    ExecutorService exs = Executors.newSingleThreadExecutor();            // (5)
    Future<BigInteger> future = null;
    try {
      future = exs.submit(() -> bigFactorial(number));                    // (6)
      BigInteger result = future.get(timeout, unit);                      // (7)
      System.out.println(“Factorial: ” + result);                         // (8)
    } catch (TimeoutException e) {                                        // (9)
      System.out.println(e);
      System.out.println(“cancel(true):  ” + future.cancel(true));        // (10)
      System.out.println(“isCancelled(): ” + future.isCancelled());       // (11)
    } catch (InterruptedException | ExecutionException e) {
      System.out.println(e);                                              // (12)
    } finally {
      exs.shutdown();
    }
  }
  private static void scheduledTaskCancellation() {                       // (13)
    System.out.println(“Scheduled task cancellation:”);
    int number = 100000;
    long delay = 10;
   
TimeUnit unit = TimeUnit.MILLISECONDS;
    System.out.println(“NUMBER: ” + number + “, DELAY: ” + delay + ” ” + unit);
    ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);   // (14)
    try {
      Future<BigInteger> future = ses.submit(() -> bigFactorial(number)); // (15)
      ses.schedule(() -> future.cancel(true), delay, unit);               // (16)
      TimeUnit.SECONDS.sleep(1);                                          // (17)
      System.out.println(“isCancelled(): ” + future.isCancelled());       // (18)
    } catch (InterruptedException e) {
      System.out.println(e);
    } finally {
      ses.shutdown();
    }
  }
  public static void main(String[] args) {
    timedTaskCancellation();
    System.out.println();
    scheduledTaskCancellation();
  }
}

Probable output from the program:

Click here to view code image Timed task cancellation:
NUMBER: 100000, TIMEOUT: 1 SECONDS
java.util.concurrent.TimeoutException
pool-1-thread-1 interrupted.
cancel(true):  true
isCancelled(): true
Scheduled task cancellation:
NUMBER: 100000, DELAY: 10 MILLISECONDS
pool-2-thread-1 interrupted.
isCancelled(): true