“Callable” vs “Runnable” Tasks in Java Concurrent Programming
When we write multi-threaded applications in Java, we are predisposed to implementing threaded classes by using the “Runnable” interface.
Your class has to simply implement this interface and override the run method.
For trivial use cases, we can directly start the thread by invoking the “start” method, and the flow of control is delegated to the run method as a result.
However, in most applications we end up using a thread pool, which manages the worker threads and facilitates task execution whenever a task is submitted to the pool.
Java provides a wide variety of thread pools, and also allows programmers to create their own implementation of a thread pool.
The process to submit threaded tasks to the pool is also quite standard.
In certain conditions, we may want our threads to do a “bit more” than to just execute a task.
In this context, it is important to understand the use cases of using Runnable vs Callable.
1. Returning a value from an executing thread
On many occasions, you may want to return a value from an executing thread.
This is where a “Callable” task comes in handy.
The Java ExecutorService APIs allow for accepting a task of type Callable, and returns a “Future” task.
This can be useful for certain use cases.
However, one of the more important choices to use Callable is given below.
2. Ability to throw checked exceptions from an executing thread
One of the important considerations of Callable is the ability for programmers to throw exceptions from an executing thread.
This enables exception handling from our multi threaded applications, and enables graceful recovery from exceptions.
If we review the signature of the “call” method, we would see, that it throws a generic exception –
3. Other Scenarios
The Callable interface implementations can also be used in conjunction with FutureTask.
The FutureTask class accepts a Callable implementation.
The FutureTask can be submitted to a thread pool executor and we can retrieve the execution results using the standard Future APIs.
Code Snippet Below
public class CallableInsideFutureTask { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); FutureTask<String> myTask = new MyTask(new CallableTest()); executor.submit(myTask); try { myTask.get(); } catch (Exception ex ) { ex.printStackTrace(); } executor.shutdownNow(); } }
In this example, the CallableTest class has to implement the Callable interface.
If you liked this post, feel free to connect on LinkedIn.
Published on Java Code Geeks with permission by Aayush, partner at our JCG program. See the original article here: “Callable” vs “Runnable” Tasks in Java Concurrent Programming Opinions expressed by Java Code Geeks contributors are their own. |
cool, that makes me think that you could throw an exception after a fixed timeout, that way “get” would wait only for a timeout period and would not block the main thread indefinitively. Intresting….