I am trying to understand how a Callable
is able to return a value when it is run on a different thread.
I am looking in the classes Executors
, AbstractExecutorService
, ThreadPoolExecutor
and FutureTask
, all available in java.util.concurrent
package.
You create an ExecutorService object by calling a method in Executors (e.g. newSingleThreadExecutor()
). Then you can pass a Callable object with ExecutorService.submit(Callable c)
.
Since the call()
method is run by a thread provided by the ExecutorService
, where does the returned object "jump" back to the calling thread?
Look at this simple example:
1 ExecutorService executor = Executors.newSingleThreadExecutor();
2 public static void main(String[] args) {
3 Integer i = executor.submit(new Callable<Integer>(){
4 public Integer call() throws Exception {
5 return 10;
6 }
7 }).get();
8 System.out.print("Returns: " + i + " Thread: " + Thread.currentThread.getName());
9 // prints "10 main"
10 }
How is it possible that the integer in the call method, which is run by a separate thread, is returned to the Integer object (row 3) so it can be printed by the System.out
statement in the main thread (row 7)?
Isn´t it possible for the main thread to be run before the ExecutorService
has run its thread, so that the System.out statement
prints null?
A Callable is similar to Runnable except that it can return a result and throw a checked exception.
Interface Callable<V>A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call. The Callable interface is similar to Runnable , in that both are designed for classes whose instances are potentially executed by another thread.
The return type of the call() method of the interface is an Object. Hence, the call() method returns an Object. The return type of the run() method of the interface is void. Hence, the run() method returns void.
Simply, you make an object callable by overriding the special method __call__() . __call__(self, arg1, .., argn, *args, **kwargs) : This method is like any other normal method in Python.
How is it possible that the integer in the call method, which is run by a separate thread, is returned to the Integer object
ExecutorService.submit(...)
does not return the object from call()
but it does return a Future<Integer>
and you can use the Future.get()
method to get that object. See the example code below.
Isn´t it possible for the main thread to be run before the ExecutorService has run its thread, so that the System.out statement prints null?
No, the get()
method on the future waits until the job finishes. If call()
returned null then get()
will otherwise it will return (and print) 10
guaranteed.
Future<Integer> future = executor.submit(new Callable<Integer>(){
public Integer call() throws Exception {
return 10;
}
});
try {
// get() waits for the job to finish before returning the value
// it also might throw an exception if your call() threw
Integer i = future.get();
...
} catch (ExecutionException e) {
// this cause exception is the one thrown by the call() method
Exception cause = e.getCause();
...
}
Have a look on ExecutorService.submit() method :
<T> Future<T> submit(Callable<T> task)
:
Submits a value-returning task for execution and returns a Future representing the pending results of the task. The Future's get method will return the task's result upon successful completion.
If you would like to immediately block waiting for a task, you can use constructions of the form result = exec.submit(aCallable).get();
Q. Isn´t it possible for the main thread to be run before the ExecutorService has run its thread, so that the System.out statement prints null?
--> Future<T>.get() Waits if necessary for the computation to complete, and then retrieves its result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With