Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the advantage of using FutureTask over Callable?

Tags:

There are two approaches to submitting and polling task for result

FutureTask futureTask = new FutureTask<String>(callable); 
  1. Use combination of Callable and Future and submit on ExecutorService. Retrieve result using future.get().

    Future future = service.submit(callable); 
  2. Use FutureTask. This will wrap Callable and then retrieve result using FutureTask.

    service.execute(task); 

What is the advantage of using FutureTask over Callable + Future combination ?

like image 385
Amrish Pandey Avatar asked Jun 22 '15 09:06

Amrish Pandey


People also ask

What is the use of FutureTask in Java?

A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable , a FutureTask can be submitted to an Executor for execution. In addition to serving as a standalone class, this class provides protected functionality that may be useful when creating customized task classes.

What's the difference between Future and FutureTask in Java?

Future is a base interface and defines the abstraction of an object which promises results to be available in the future while FutureTask is an implementation of the Future interface.

What is the difference between Future and Callable interface in Java?

Observe that Callable and Future do two different things – Callable is similar to Runnable, in that it encapsulates a task that is meant to run on another thread, whereas a Future is used to store a result obtained from a different thread.

What is the difference between Callable and runnable interface?

A callable interface throws the checked exception and returns the result. A runnable interface, on the other hand, shows the result or throws an exception, but does not do both.


2 Answers

Almost certainly none at all. A quick browse on GrepCode of the AbstractExecutorService shows each of these methods are simply helper methods that ultimately wrap the Callable/Runnable in a Future for you.

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {     return new FutureTask<T>(runnable, value); }  protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {     return new FutureTask<T>(callable); }  public Future<?> submit(Runnable task) {     // ...     RunnableFuture<Object> ftask = newTaskFor(task, null);     execute(ftask);     return ftask; }  public <T> Future<T> submit(Runnable task, T result) {     // ...     RunnableFuture<T> ftask = newTaskFor(task, result);     execute(ftask);     return ftask; }  public <T> Future<T> submit(Callable<T> task) {     // ...     RunnableFuture<T> ftask = newTaskFor(task);     execute(ftask);     return ftask; } 
like image 121
OldCurmudgeon Avatar answered Oct 13 '22 00:10

OldCurmudgeon


Using Future we can find out the status of the Callable task and get the returned Object. It provides get() method that can wait for the Callable to finish and then return the result.

Future provides cancel() method to cancel the associated Callable task. There is an overloaded version of get() method where we can specify the time to wait for the result, it’s useful to avoid current thread getting blocked for longer time. There are isDone() and isCancelled() methods to find out the current status of associated Callable task.

Here is a simple example of Callable task that returns the name of thread executing the task after one second. We are using Executor framework to execute 100 tasks in parallel and use Future to get the result of the submitted tasks.

    import java.util.ArrayList;     import java.util.Date;     import java.util.List;     import java.util.concurrent.Callable;     import java.util.concurrent.ExecutionException;     import java.util.concurrent.ExecutorService;     import java.util.concurrent.Executors;     import java.util.concurrent.Future;      public class MyCallable implements Callable<String> {          @Override         public String call() throws Exception {             Thread.sleep(1000);             //return the thread name executing this callable task             return Thread.currentThread().getName();         }          public static void main(String args[]){             //Get ExecutorService from Executors utility class, thread pool size is 10             ExecutorService executor = Executors.newFixedThreadPool(10);             //create a list to hold the Future object associated with Callable             List<Future<String>> list = new ArrayList<Future<String>>();             //Create MyCallable instance             Callable<String> callable = new MyCallable();             for(int i=0; i< 100; i++){                 //submit Callable tasks to be executed by thread pool                 Future<String> future = executor.submit(callable);                 //add Future to the list, we can get return value using Future                 list.add(future);             }             for(Future<String> fut : list){                 try {                     //print the return value of Future, notice the output delay in console                     // because Future.get() waits for task to get completed                     System.out.println(new Date()+ "::"+fut.get());                 } catch (InterruptedException | ExecutionException e) {                     e.printStackTrace();                 }             }             //shut down the executor service now             executor.shutdown();         }     } 

Where as FutureTask is base concrete implementation of Future interface and provides asynchronous processing. It contains the methods to start and cancel a task and also methods that can return the state of the FutureTask as whether it’s completed or cancelled. We need a callable object to create a future task and then we can use Java Thread Pool Executor to process these asynchronously.

Let’s see the example of FutureTask with a simple program.

Since FutureTask requires a callable object, we will create a simple Callable implementation.

    public class MyCallable implements Callable<String> {      private long waitTime;      public MyCallable(int timeInMillis){         this.waitTime=timeInMillis;     }     @Override     public String call() throws Exception {         Thread.sleep(waitTime);         //return the thread name executing this callable task         return Thread.currentThread().getName();     }  }      import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException;  public class FutureTaskExample {      public static void main(String[] args) {         MyCallable callable1 = new MyCallable(1000);         MyCallable callable2 = new MyCallable(2000);          FutureTask<String> futureTask1 = new FutureTask<String>(callable1);         FutureTask<String> futureTask2 = new FutureTask<String>(callable2);          ExecutorService executor = Executors.newFixedThreadPool(2);         executor.execute(futureTask1);         executor.execute(futureTask2);          while (true) {             try {                 if(futureTask1.isDone() && futureTask2.isDone()){                     System.out.println("Done");                     //shut down executor service                     executor.shutdown();                     return;                 }                  if(!futureTask1.isDone()){                 //wait indefinitely for future task to complete                 System.out.println("FutureTask1 output="+futureTask1.get());                 }                  System.out.println("Waiting for FutureTask2 to complete");                 String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);                 if(s !=null){                     System.out.println("FutureTask2 output="+s);                 }             } catch (InterruptedException | ExecutionException e) {                 e.printStackTrace();             }catch(TimeoutException e){                 //do nothing             }         }      }  } 
like image 30
Mudassar Avatar answered Oct 12 '22 22:10

Mudassar