One of the benefits of the Java executor framework is that we can run concurrent tasks that may return a single result after processing the tasks. The Java Concurrency API achieves this with the following two interfaces Callable
and Future
.
1. Java Callable and Future interfaces
1.1. Callable
Callable
interface has the call()
method. In this method, we have to implement the logic of a task. The Callable
interface is a parameterized interface, meaning we have to indicate the type of data the call()
method will return.
2.2. Future
Future
interface has methods to obtain the result generated by a Callable
object and to manage its state.
2. Java Callable Future Example
In this example, We are creating a FactorialCalculator
which is of type Callable
. It means we will override it’s call()
method and after calculation, we will return the result from call()
method. This result later can be retrieved from Future
reference held by main program.
public class FactorialCalculator implements Callable<Integer> { private Integer number; public FactorialCalculator(Integer number) { this.number = number; } @Override public Integer call() throws Exception { int result = 1; if ((number == 0) || (number == 1)) { result = 1; } else { for (int i = 2; i <= number; i++) { result *= i; TimeUnit.MILLISECONDS.sleep(20); } } System.out.println("Result for number - " + number + " -> " + result); return result; } }
Now let’s test the above factorial calculator using two threads and 4 numbers.
package com.howtodoinjava.demo.multithreading; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class CallableExample { public static void main(String[] args) { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2); List<Future<Integer>> resultList = new ArrayList<>(); Random random = new Random(); for (int i=0; i<4; i++) { Integer number = random.nextInt(10); FactorialCalculator calculator = new FactorialCalculator(number); Future<Integer> result = executor.submit(calculator); resultList.add(result); } for(Future<Integer> future : resultList) { try { System.out.println("Future result is - " + " - " + future.get() + "; And Task done is " + future.isDone()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } //shut down the executor service now executor.shutdown(); } }
Program output.
Result for number - 4 -> 24 Result for number - 6 -> 720 Future result is - - 720; And Task done is true Future result is - - 24; And Task done is true Result for number - 2 -> 2 Result for number - 6 -> 720 Future result is - - 720; And Task done is true Future result is - - 2; And Task done is true
Here we sent a Callable
object to be executed in an executor using the submit()
method. This method receives a Callable
object as a parameter and returns a Future
object that we can use with two main objectives –
- We can control the status of the task – we can cancel the task and check if it has finished. For this purpose, we have used the
isDone()
method to check if the tasks had finished. - We can get the result returned by the call() method. For this purpose, we have used the
get()
method. This method waits until theCallable
object has finished the execution of thecall()
method and has returned its result.If the thread is interrupted while the
get()
method is waiting for the result, it throws anInterruptedException
exception. If thecall()
method throws an exception, this method throws anExecutionException
exception.
The Future
interface provides another version of the get()
method i.e. get(longtimeout,TimeUnitunit). This version of the get method, if the result of the task isn’t available, waits for it for the specified time. If the specified period of time passes and the result isn’t yet available, the method returns a null
value.
Happy Learning !!
lin
I just saw in Java 8 ,The Future‘s method get(longtimeout,TimeUnitunit)shouldt hrows TimeoutException if the wait timed out, not return null .
Karthik
Yep, you are right it should throw the TimeoutException and not null. Here is the implementation.
basil
how to do read file content and write same content into another file using two callable thread?
Indu
Good One
ganna99
Thank you for the great article.
But, how to run task periodically (every n seconds) and retrieve some result, which is needed in further processing? Is it wise to use in indefinite while(true) loop, the method schedule (Callable task, long delay, TimeUnit timeunit)?
Dushyant Sapra
Here is the code
class TestTRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
System.out.println(“Rejected Execution Handler For Thread ” + Thread.currentThread().getName());
Thread.sleep(1000);
} catch (Exception e2) {
// TODO: handle exception
}
executor.execute(r);
}
}
class TestTTask implements Callable {
@Override
public String call() {
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
return Thread.currentThread().getName();
}
}
public class TestT {
public static void main(String[] args) throws InterruptedException, ExecutionException {
BlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(
1);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2,
1000, TimeUnit.MILLISECONDS, arrayBlockingQueue,
new TestTRejectedExecutionHandler());
for (int iLoop = 0; iLoop < 100; iLoop++) {
Future future = threadPoolExecutor.submit(new TestTTask());
System.out.println(future.get());
}
}
}
Dushyant Sapra
Here is my Example.
In this If i call future.get(), then rejectedExecution doesn’t get executed, but if comment that line(future.get()) then it is getting executed.
Please Suggest a way forward.
Shaik
Hi Dushyant,
get() is blocking call so calling that method after submitting will not give better result since you are waiting the just submitted task. Replace the loop with the below code instead.
Dushyant Sapra
Hello
How would you handle Rejected Task if i use ArrayBlockingQueue and choose to implement my own RejectedExecutionHandler Class.
Dushyant Sapra
Subrat Kumar
Very nice article about Future, Callable and Executor. I wandered here and there for basic information and use, but didn’t find as easiest as this. Thanks Lokesh. Thanks a lot.
venkat
very very useful information, to know any new subject I will first search in your site. if I didnot find then I go for google search.
Lokesh Gupta
Thanks Venkat. I am glad that my work is of some use !!
Priyank Jain
One of the easiet article to unerstand ThreadPool in details.
Venkata Sriram
Thanks for nice article sir.