Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a Callable work under the hood? How is it possible for a callable object to return a value?

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?

like image 202
Rox Avatar asked Aug 10 '12 14:08

Rox


People also ask

Can Callable return a value?

A Callable is similar to Runnable except that it can return a result and throw a checked exception.

How does Callable work in Java?

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.

What is the return type of Callable interface?

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.

How do you make an object Callable?

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.


2 Answers

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();
   ...
}
like image 64
Gray Avatar answered Oct 31 '22 01:10

Gray


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.

like image 30
Nandkumar Tekale Avatar answered Oct 31 '22 03:10

Nandkumar Tekale