Friday 14 April 2017

Callable and Future.

This article is in continuation of Executor Service. Please do read previous articles for detail about Executor Service. Callable is another way of writing task same as Runnable but it comes with additional benefits of returning results after completion of task.



1. What is Callable?

Answer: Callable<V> interface provides way of writing task same as Runnable but it has additional features of returning result after completion of task.
Callable interface has call() method which is same as run() method of Runnable interface. Only difference is that return type of run() method is void as it doesn't return anything but call() method has return type which is same as type of Callable.
Example: 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceExample {
 public static void main(String[] args) {
  Task myTaks = new Task();
  ExecutorService executorService = Executors.newScheduledThreadPool(3); //We are creating a Thread pool of fixed size in this case 5.
  executorService.submit(myTaks);
 }
}


class Task implements Callable<Integer>{
 @Override
 public Integer call() {
  return 2;
 }
}
In above code we have Callable task of type Integer. As I said above return type of call() method would be same as type of Callable. In this code we have return type of call() as Integer same as type of task.
In above code we have returned 2 from call method. Now next question would come in mind how you will receive result that you have returned from call() method.
Since in this above code call() method is being executing by say thread-1 and we have started thread-1 from main() method. So the point is you are returning value from thread-1 and you need to receive it inside main thread. 
We can not directly return result form one thread to another thread, since both the thread has their own stack.

To solve above problem Java has concept of Future. Future class is use to receive value returned from call() method of Callable.


2. What is Future?

AnswerFuture class provides a way of receiving result which we return from call() method of Callable. If you check return type of Java's submit() method it is a Future object. submit() method immediately returns Future object. Then we can use Future object's get() method to get the result.
Note: get() method is a blocking method i.e it waits for result till call() method completes it's execution and returns value.
Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 ExecutorServiceExample {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
  Task myTaks = new Task();
  ExecutorService executorService = Executors.newScheduledThreadPool(3);
  Future future =  executorService.submit(myTaks);
  Integer result = (Integer) future.get();
  System.out.println("Result is ::"+result);
 }
}

class Task implements Callable<Integer>{
 @Override
 public Integer call() {
  return 2;
 }
}
In above code at line number 11 we have got Future object immediately. Then we have invoked get() method which will wait for call() method to complete and return result. Once call() method will return result we will get that in result variable.
In above code since we don't have any business logic inside call() method hence we got result immediately but in real scenario call() method takes some time to execute hence get() will remain block for that time period.
To simulate same let's consider below code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 ExecutorServiceExample {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
  Task myTaks = new Task();
  ExecutorService executorService = Executors.newScheduledThreadPool(3);
  Future future =  executorService.submit(myTaks);
  Integer result = (Integer) future.get();
  System.out.println("Result is ::"+result);
 }
}

class Task implements Callable<Integer>{
 @Override
 public Integer call() throws InterruptedException {
  Thread.sleep(5000); // To simulate some task is being done
  return 2;
 }
}
Now in this case you will notice that get() method remains block for 5 seconds and result get printed after that.
Future is way of asynchronous communication as get() method wait for result while threads process in background.
Note: Future class has isDone() method which can be invoked to check whether a task is completed or still running. isDone() method returns true if task completed(call() method completed) otherwise false.


3. How exception works in case of Callable and Future? 

AnswerAs we know exception propagates inside stack only and each thread has their own stack. And in this case we have two different thread i.e. call() method is running inside say thread-1 and get() method is waiting inside main thread. So Java internally handles exception throws from call() method.
get() method of Future class throws 2 exception:
1. ExecutionException: If any exception occurs inside call() method then Java warps that exception inside ExecutionException and throws it to get() method and then get() method propagates ExcutionException to further.
2. InterrupteException: If current thread got interrupted(in above code it main thread) while waiting then Java throws InterrupteException.
Example: If you run below code you will get ExecutionException.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 ExecutorServiceExample {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
  Task myTaks = new Task();
  ExecutorService executorService = Executors.newScheduledThreadPool(3);
  Future future =  executorService.submit(myTaks);
  Integer result = (Integer) future.get();
  System.out.println("Result is ::"+result);
 }
}

class Task implements Callable<Integer>{
 @Override
 public Integer call() throws Exception {
  throw new Exception();
 }
}

No comments:

Post a Comment