Sometime back I wrote a post about Java Callable Future interfaces that we can use to get the concurrent processing benefits of threads as well as they are capable of returning value to the calling program. 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.
package com.journaldev.threads;
import java.util.concurrent.Callable;
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();
}
}
Here is an example of FutureTask method and it’s showing commonly used methods of FutureTask.
package com.journaldev.threads;
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
}
}
}
}
When we run above program, you will notice that it doesn’t print anything for sometime because get()
method of FutureTask waits for the task to get completed and then returns the output object. There is an overloaded method also to wait for only specified amount of time and we are using it for futureTask2. Also notice the use of isDone()
method to make sure program gets terminated once all the tasks are executed. Output of above program will be:
FutureTask1 output=pool-1-thread-1
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
FutureTask2 output=pool-1-thread-2
Done
As such there is no benefit of FutureTask but it comes handy when we want to override some of Future interface methods and don’t want to implement every method of Future interface.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Would you please show the usage of overloaded submit(Runnable, T) method.
- Pran
Hello Thank you for a wonderful series of tutorials on Executor framework. May I ask two basic questions regarding this tutorial: 1. why on the 2nd example ‘while (true)’ is needed? what changes if we skip it? 2. what does futureTask1.get() / futureTask2.get() return ? isn’t it callable1.call() / callable2.call() ? if so, why why we output futureTask1.get() in negation if(!futureTask1.isDone())? what do we expect to ‘get’ when the task did not finish yet? Thank you
- Andrey
hi , i am usimg above code by creating inner class, but task execute at once only not continuesly execute, i want execute continuesly with 1 sec delay…
- Nikhil
Hi, i am using above code, my thread run only once i want execute continues with 1 sec delay…
- Nikhil
Nice article… good job. Just one thing about this web site -You have a very annoying popup ( FREE eBook… ) on your web page, which cannot be closed due to over-lapping share-bar. Please get rid of this…
- Shashi
Here in the above example we are implementing callable and passing it to execute(). execute() only accepts Runnable,so i think you should be using submit() here.
- Shivam
Bydefault, Future task is run asynchronously , so will be executed in a different Thread from the one which added it by calling the execute method. For example " Thread1" called execute method , Futuretask will be executed in “Thread2”. Thread1 can get the result by calling " get" method of Futuretask it passed. On the other hand , callable by default will be executed on same Thread , unless you are using custom executor that starts a new thread. If " Thread1" submitted callable, the callable will be run on Thread1, unless the executor you are using spawns a new thread and run the callable in that thread Look at AsyncTask in android, attribute " mWorker" is a callable , which then is passed into “mFuture” which is a Future task… It is the Futuretask which will be passed to ThreadPoolExecutor., so future task executes asynchronously in another thread - the mWorker that it has. One more thing mWorker does is it makes the thread in which it is running a background thread as well.
- H
Good examples. keep posting and thanks for your dedication
- mbappe
Nice job …keep posting…
- navin murrari
Hi Pankaj, Thanks for article. Well, for all of them… keep up good work. Anyway, one thing bothers me. Why not to use submit(Callable) instead? Is this solution has some benefits i can not see now? Cheers.
- Josiash