Why we need Callable Interface ?
We can create a thread in two ways
- The first one is to extend the thread class.
- The second one is to use Runnable Interface to create threads.
However, one of the missing features of Runnable is that we cannot return the result returned by the thread when the thread terminates (that is, when run () completes). To support this feature, a Callable interface is provided in Java. The Java Callable interface, java.util.concurrent.Callable, represents an asynchronous task which can be executed by a separate thread. For instance, it is possible to submit a Callable object to a Java ExecutorService which will then execute it asynchronously.
Callable Interface Definition -
public interface Callable<V> { V call() throws Exception; }
The call() method can return a result. If the task is executed asynchronously, the result is typically propagated back to the creator of the task via a Java Future. This is the case when a Callable is submitted to an ExecutorService for concurrent execution.
The call() method can also thrown an Exception in case the task fails during execution.
Implementing Callable Interface -
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { String test ="Hello this is testing"; return test; } }
Future Interface In Java -
Future interface has methods to obtain the result generated by a Callable object and to manage its state
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning) V get(); V get(long timeout, TimeUnit unit); boolean isCancelled(); boolean isDone(); }
// Java Callable Future Example public static void main(final String[] arguments) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newSingleThreadExecutor(); System.out.println("Factorial of 10!"); Future<Long> res10 = executor.submit(new FactorialService(10)); System.out.println("Factorial fof 20!"); Future<Long> res20 = executor.submit(new FactorialService(20)); Long factorial10 = res10.get(); System.out.println("10! = " + factorial10); Long factorial20 = res20.get(); System.out.println("20! = " + factorial20); executor.shutdown(); } static class FactorialService implements Callable<Long> { private int number; public FactorialService(int number) { this.number = number; } @Override public Long call() throws Exception { return factorial(); } private Long factorial() throws InterruptedException { long result = 1; while (number != 0) { result = number * result; number--; Thread.sleep(100); } return result; } } } This will produce the following output. Output Factorial of 10! Factorial of 20! 10! = 3628800 20! = 2432902008176640000
Here, we use the Submit () method to send a Callable object to be executed in the port. This method takes a Callable object as a parameter and returns a Future object.
Future Object we can use with two main objectives –
1. We can control the status of the task - we can cancel the task and check if it has ended. For this purpose, we used isDone () method to verify tasks are finished.
2. We can get the returned result by call () method. To do this, we use the get () method. This method waits until the Callable object completes the call () method and returns the result.
Hope this will help you