Java Thread with Callable Interface


In the previous chapter we saw how to create a thread by implementing Java Runnable interface.

In this chapter we will see how to create Java Thread with Callable interface and also what are differences between Runnable and Callable.

3. Implement Callable

import java.util.concurrent.Callable;


public class CallableThread implements Callable<String>{

 @Override
 public String call() throws Exception {
  System.out.println("in Callable");
  
  
  return "finished";
 }
 

}


Value can be returned from Callable

The class here looks very similar to the class in the previous chapter where we implemented Runnable interface. It is just that Callable class takes a generic parameter. In the example we have mentioned this generic type as String.
As Runnable has a run() mthod Callable has call() method. The difference is that call() has a return type while run() does not. And the return type should be same as the generic defines while implementing Callable. In our case String.
But here the catch, in Runnable we do not have access of the thread once it is started. Meaning that we can not check the thread whether it is completed or there was an Excpetion in the execution. Here in callable we have the handle to the thread we started. By this handle we can check if the thread has completed or there was an Exception. Lets see the test code.

To test this class lets create a class

import java.util.concurrent.FutureTask;

public class ThreadTest {

 public static void main(String args[]) {
  CallableThread callableThread = new CallableThread();
  FutureTask futureTask = new FutureTask(callableThread);
  futureTask.run();
  System.out.println("hi");
  try {
   System.out.println(futureTask.get());
  } catch (Exception e) {
  }
 }
}


Here we have first created istance of CallableThread class. Then instead of creating a Thread class instance and passing instance of callable to its constructor as we did for Runnable we will create a instance of FutureTask and pass the instance of CallableThread to its contructor. To start the thread we need to call the run() mthod on futureTask instance. Please note that the run() method here has the return type void. So then how to collect the value returned from call().

Lets run the class and print the output.
in Callable
hi
finished

As seend in the code after starting the thread by calling the run() method on the futureTask, we have called futureTask.get() method. This method's return type is the same as that was of the generic type provided while implementing Callable that is String. On calling the futureTask.get() method the current thread i.e. main thread will wait until the thread CallableThread is completed and the value is returned. If the CallableThread computation is already finished then the get() methdo will just return the value, in our case 'finished'.

This is the biggest difference between Runnable and Callable. Callable provides us a handle to the thread by which we can check status, return value and exception of that thread which is not possible in Runnable and Thread class.

Exception can be thrown from Callable:

Also when we look carefully at the call() method in the CallableThread, the method signatures defines 'throws Exception'. This is not possible in Runnable.run() method. The compiler will give a error on writing throws Exception 'Exception Exception is not compatible with throws clause in Runnable.run()'. What we can write on Runnable.run() is 'throws RuntimeException'. The behind the run() method can throw only a RuntimeException is that the compiler has no bonding on the caller of this method to catch the Exception. Also with Runnable we do not know when calling start() whether the thread has started, completed, or isInProgress. So it is possible that when we try to catch the Exception of a runnable the thread might not have yet started. Lets see this concept by a Example

public class RunnableThread implements Runnable {
 public void run() throws RuntimeException{
  System.out.println("MyThread run called");
  for(int i=0;i<=5;i++){
   System.out.println(i);
  }
  throw new NullPointerException();
 }
}


public class ThreadTest {

 public static void main(String args[]){
  RunnableThread  runnableThread = new RunnableThread();
  Thread thread = new Thread(runnableThread);
  try{
   thread.start();
  }catch(Exception e){
   System.out.println("caugth");
   e.printStackTrace();
  }
  System.out.println("Runnable thread started");
 }
}

Output
Runnable thread started
MyThread run called
0
1
2
3
4
5

As seen above a NullPinterException is thrown from the run method. We have tried to catch it by placing the try-catch on thread.start(). But the execution of try- catch and main completes before starting the Thread runnable and the execution never comes in catch block and prints "caught". The reason is the execution is not guaranteed.

In case of Callable the futureTask.get method guarantees the completion of thread. That is the main will wait until the thread complete. So here it is logical to throw Checked Exception and catch it as well.

Java Thread class >> Java Runnable Interface >> Java Callable Interface  >> Java CountDownLatch  >> Java CyclicBarrier

Share the post