Future and FutureTask in Java Concurrency with Example

A Future interface implementation object is used to represent the result of an asynchronous computation in Java concurrency.

A Future interface provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result is retrieved using Future's get method when the computation has completed, and it blocks until it is completed. Cancellation is performed by the cancel method (cancel(boolean mayInterruptIfRunning)). The cancel method returns true if the task was cancelled, and will not have any effect and return false if the task has already completed or already cancelled, or could not be cancelled for some reason. After a successful cancel, tasks that have not started will not run. The mayInterruptIfRunning parameter determines whether already started tasks should be interrupted in an attempt to stop the task. Additional methods isDone() and isCancelled() determine if the task completed normally or was cancelled.

Once a computation has completed, the computation cannot be cancelled. If a task completes  by  throwing  an  exception,  corresponding Future.get rethrows it wrapped  in  an  ExecutionException;  and if  it  was  cancelled,  Future.get throws CancellationException. If Future.get throws ExecutionException, the underlying exception can be retrieved with getCause. The submit method in the ExecutorService return a Future when you submit a Runnable or a Callable. The Runnable or Callable is safely published from the submitting thread to the thread that will execute the task. The result value for a Future is also safely published from the thread in which it was computed to any thread that retrieves it via get.

FutureTask is an implementation of Future. You can explicitly instantiate a FutureTask for a given Runnable or Callable. A FutureTask can be submitted to an Executor for execution as FutureTask implements Runnable. FutureTask can also be executed directly by calling its run method. Once a FutureTask enters the completed state, it stays in that state forever. If the task is completed. FutureTask constructors can accept either Callable or Runnable.

Callable is similar to Runnable, but it can return result unlike Runnable. Callable can be in one of three states: waiting to run, running, or completed. Completion can be normal completion, cancellation, and exception. Tasks  described  by  Callable  can  throw  checked  and  unchecked  exceptions,  and  any  code  can  throw  an  Error. When used with Future, anything  thrown from the Callable  is  wrapped  in  an  ExecutionException  and  re-thrown  from  Future.get.  The  code  that  calls  get must  deal  with  the  possibility  of  ExecutionException  (and  the unchecked  CancellationException). The cause of the ExecutionException is returned as a Throwable and can be retrieved with getCause method.

 

Example: FutureTaskExample.java

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.FutureTask;

 

public class FutureTaskExample {

 

        public static void main(String[] args) {

                FutureTask<String> future = new FutureTask<>(new CallableTask());

                //Cancelling code before run

                /*boolean b = future.cancel(true);

                System.out.println("Cancelled="+b);*/

                future.run();

          //Cancelling code after run

                /*boolean b = future.cancel(true);

                System.out.println("Cancelled="+b);*/

                try {

            String result = future.get();

            System.out.println("Result="+result);

    } catch (InterruptedException | ExecutionException e) {

            System.out.println("EXCEPTION!!!");

        e.printStackTrace();

    }

        }

}

 

class CallableTask implements Callable<String>{

        @Override

  public String call() throws Exception {

          System.out.println("Executing call() !!!");

          /*if(1==1)

                throw new java.lang.Exception("Thrown from call()");*/

          return "success";

  }

}

Output will be:

Executing call() !!!

Result=success

 

TO DO (To understand more):

  1. Remove the block comment (/*…*/) on the cancel code before run. You will get Cancelled=true followed by CancellationException. The run() method don’t have any effect and Future.get throws the CancellationException.
  2. Comment the try-catch block with Future.get. You will get Cancelled=true, but no exception. The run() method don’t have any effect and Future.get was throwing the CancellationException.
  3. Comment the cancel code before run as before, uncomment try-catch block with Future.get as before, and uncomment cancel code after run. You will see Executing call() !!! followed by Cancelled=false. Calling cancel on already done task has no effect, it just return false.
  4. Comment the cancel code before/after run as before, and uncomment the exception code block comment (/*…*/) in the call method of CallableTask class. You will see Executing call() !!!, EXCEPTION!!!, and java.util.concurrent.ExecutionException: java.lang.Exception: Thrown from call()…
  5. Exception is thrown only when Future.get is called, even if it is thrown from within call. If no call to Future.get, no exception will be thrown out. Comment the try-catch block with Future.get. You will see no exception.
  6. Also, try isDone() and isCancelled() methods.

 

Search the Web

Custom Search

Searches whole web. Use the search in the right sidebar to search only within javajee.com!!!