Engineering Full Stack Apps with Java and JavaScript
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.
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):