Callable and Runnable….. & Need of Completable Future(part-3)
Before Reading this blog please go through for better understanding
Why Callable …..?
In previous blogs…. In all examples tasks execute through thread-pool does not return any results, that means all examples implemented with the Runnable interface. if tasks execute through thread pool has some outcome, then ….. we need to implement through callable interface.
Runnable interface is a functional interface, which implements the run method. run() method is a void method. execute() method of the Executor Thread-pool took Runnable interface as parameter.
Callable is also a functional interface as similar as the Runnable interface. which implements call() method. it has a return type. it is not an void method. submit() method of the ExecutorThread-pool took Callable interface as parameter. it will give results as Future
submit() method accepts both Runnable and callable as parameters. but it returns Future when we send callable interface as a parameter.
Future
Future is a Object which creates at the time of the task executing, when each task is completed, result is stored in the Future Object. if you use the method future.get() then it is wait until the task get completed and then it will give result.
we can understand callable and future through below example
- In above example Each task implements the callable interface and it returns the String. there are 10 tasks and 3 threads executes these 10 tasks asynchronously with the Fixed thread Pool Executor.
- when the task-1 executes then there is no string in Future Object. if task executed completely then only string is stored in Future Object.
- when we perform a get() operation on the Future Object of a particular task, main thread is blocked and it will wait until the task is completed even though if task is not completed at that time and it gives result while we iterating all Future Objects of these 10 tasks.
Note : Try not to use Future.get() method in real Time, if task took more time, main thread will block and it may lead to dead-lock condition.Always use with get() method with specific time period
future.get(long, TimeUnit);
Advantage of Callable
List<Future<?>> futures = executorPool.invokeAll(List<class extends Callable>);
Future future = executorPool.invokeAny(class extends Callable);
This invokeAll() and invokeAny() could have an added advantage to callable then Runnable.
use-case : if you have more number of tasks if you send all the tasks to the Non-blocking queue, it may lead to memory issues in real time.
if you took all rows from the big data like Cassandra and we need to perform the tasks on executor thread pool directly. it will lead to memory issues in real time.At that time invokeall() method saves us from the memory issues
if you observe the above program, it consists of 95 tasks and thread pool of 3 threads. here we are insisting only 10 tasks will submitted to the thread pool at a time. it executes in this manner
1–10 tasks — — — — 10 tasks submitted — — — — — — — — — 3 threads
10–20 tasks — — — —10 tasks submitted — — — — — — — — 3 threads
20–30 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
30–40 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
40–50 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
50–60 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
60–70 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
70–80 tasks — — — — 10 tasks submitted — — — — — — — — 3 threads
80–90 tasks — — 10 tasks submitted(seen in output picture) — 3 threads
90–95 tasks — — — — 5 tasks submitted — — — — — — — — 3 threads
Comparison Between Runnable and callable interfaces
Runnable
- it is a interface with single method . so we can apply a lambda expressions
- it can be implemented through both execute() and submit() methods of the executor thread pool.
- it can be implemented in a Thread constructor
Thread th = new Thread(Runnable runnable);
4. it does not have support for invokeAll() and invokeAny() methods of the executor thread Pool
5. it does not return any output and it does not throw any checked exceptions (exceptions which are handled during compile time)
6. Runnable interface is introduced in Java from JDK 1.0
Callable
- it is a interface with single method . so we can apply a lambda expressions
- it can be implemented through only submit() method of the executor thread pool.
- it cannot be implemented in a Thread constructor
4. it have support for invokeAll() and invokeAny() methods of the executor thread Pool
5. it will return output through Future Object which acts like holder and it throws checked exceptions (exceptions which are handled during compile time)
6. Callable interface is introduced in Java from JDK 1.5
Is Java does Really Supports an Asynchronous Programming ?
No until java 1.7 , when Java 8 supports an Asynchronous programming when it is flexible for functional style of programming by Implementing Completable Future which is similar semantics as Promises in Java Script.
In what case completable Future Required……….
lets focus on below program
In the above program two methods getting an order and paying an order will independent of each-other and it executed asynchronously without any blocking of the main thread.
Need of Completable Future:
Let us consider we have three methods, which are dependent on each other
- orderBooking (CPU intensive)
- orderConformation (IO intensive)
- payment conformation (CPU intensive)
you need to execute all these methods as dependent for each client ,but client to client as an Independent flow as shown as below diagram without dependent of main thread.
Program Generally we write ….
Above program runs for 100 clients
Initially it runs orderBooking for 100 clients
then it runs orderConformation for 100 clients
then it runs paymentConformation for 100 clients
which is equal to sequential execution and it is completely in correct. to solve this use case completable futures are used. we will discuss in further posts