What is the difference between using the Runnable
and Callable
interfaces when designing a concurrent thread in Java, why would you choose one over the other?
This question is related to
java
multithreading
interface
runnable
callable
Callable
needs to implement call()
method while a Runnable
needs to implement run()
method.Callable
can return a value but a Runnable
cannot.Callable
can throw checked exception but a Runnable
cannot.A Callable
can be used with ExecutorService#invokeXXX(Collection<? extends Callable<T>> tasks)
methods but a Runnable
cannot be.
public interface Runnable {
void run();
}
public interface Callable<V> {
V call() throws Exception;
}
+-------------------------------------+--------------------------------------------------------------------------------------------------+
| Runnable | Callable<T> |
+-------------------------------------+--------------------------------------------------------------------------------------------------+
| Introduced in Java 1.0 of java.lang | Introduced in Java 1.5 of java.util.concurrent library |
| Runnable cannot be parametrized | Callable is a parametrized type whose type parameter indicates the return type of its run method |
| Runnable has run() method | Callable has call() method |
| Runnable.run() returns void | Callable.call() returns a value of Type T |
| Can not throw Checked Exceptions | Can throw Checked Exceptions |
+-------------------------------------+--------------------------------------------------------------------------------------------------+
The designers of Java felt a need of extending the capabilities of the Runnable
interface, but they didn't want to affect the uses of the Runnable
interface and probably that was the reason why they went for having a separate interface named Callable
in Java 1.5 than changing the already existing Runnable
interface which has been a part of Java since Java 1.0. source
Difference between Callable and Runnable are following:
It is a kind of an interface naming convention which matches with functional programming
//Runnable
interface Runnable {
void run();
}
//Action - throws exception
interface Action {
void run() throws Exception;
}
//Consumer - consumes a value/values, throws exception
interface Consumer1<T> {
void accept(T t) throws Exception;
}
//Callable - return result, throws exception
interface Callable<R> {
R call() throws Exception;
}
//Supplier - returns result, throws exception
interface Supplier<R> {
R get() throws Exception;
}
//Predicate - consumes a value/values, returns true or false, throws exception
interface Predicate1<T> {
boolean test(T t) throws Exception;
}
//Function - consumes a value/values, returns result, throws exception
public interface Function1<T, R> {
R apply(T t) throws Exception;
}
...
Purpose of these interfaces from oracle documentation :
Runnable interface should be implemented by any class whose instances are intended to be executed by a Thread
. The class must define a method of no arguments called run
.
Callable: A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.
The Callable
interface is similar to Runnable
, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable
, however, does not return a result and cannot throw a checked exception.
Other differences:
You can pass Runnable
to create a Thread. But you can't create new Thread by passing Callable
as parameter. You can pass Callable only to ExecutorService
instances.
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Use Runnable
for fire and forget calls. Use Callable
to verify the result.
Callable
can be passed to invokeAll method unlike Runnable
. Methods invokeAny
and invokeAll
perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete
Trivial difference : method name to be implemented => run()
for Runnable
and call()
for Callable
.
What are the differences in the applications of
Runnable
andCallable
. Is the difference only with the return parameter present inCallable
?
Basically, yes. See the answers to this question. And the javadoc for Callable
.
What is the need of having both if
Callable
can do all thatRunnable
does?
Because the Runnable
interface cannot do everything that Callable
does!
Runnable
has been around since Java 1.0, but Callable
was only introduced in Java 1.5 ... to handle use-cases that Runnable
does not support. In theory, the Java team could have changed the signature of the Runnable.run()
method, but this would have broken binary compatiblity with pre-1.5 code, requiring recoding when migrating old Java code to newer JVMs. That is a BIG NO-NO. Java strives to be backwards compatible ... and that's been one of Java's biggest selling points for business computing.
And, obviously, there are use-cases where a task doesn't need to return a result or throw a checked exception. For those use-cases, using Runnable
is more concise than using Callable<Void>
and returning a dummy (null
) value from the call()
method.
Callable
interface declares call()
method and you need to provide generics as type of Object call() should return -
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Runnable
on the other hand is interface that declares run()
method that is called when you create a Thread with the runnable and call start() on it. You can also directly call run() but that just executes the run() method is same thread.
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
To summarize few notable Difference are
Runnable
object does not return a result whereas a Callable
object returns a result.Runnable
object cannot throw a checked exception wheras a Callable
object can throw an
exception.Runnable
interface has been around since Java 1.0 whereas Callable
was only introduced
in Java 1.5.Few similarities include
Methods in ExecutorService interface are
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
Callable and Runnable both is similar to each other and can use in implementing thread. In case of implementing Runnable you must implement run() method but in case of callable you must need to implement call() method, both method works in similar ways but callable call() method have more flexibility.There is some differences between them.
Difference between Runnable and callable as below--
1) The run() method of runnable returns void, means if you want your thread return something which you can use further then you have no choice with Runnable run() method. There is a solution 'Callable', If you want to return any thing in form of object then you should use Callable instead of Runnable. Callable interface have method 'call()' which returns Object.
Method signature - Runnable->
public void run(){}
Callable->
public Object call(){}
2) In case of Runnable run() method if any checked exception arises then you must need to handled with try catch block, but in case of Callable call() method you can throw checked exception as below
public Object call() throws Exception {}
3) Runnable comes from legacy java 1.0 version, but callable came in Java 1.5 version with Executer framework.
If you are familiar with Executers then you should use Callable instead of Runnable.
Hope you understand.
Let us look at where one would use Runnable and Callable.
Runnable and Callable both run on a different thread than the calling thread. But Callable can return a value and Runnable cannot. So where does this really apply.
Runnable : If you have a fire and forget task then use Runnable. Put your code inside a Runnable and when the run() method is called, you can perform your task. The calling thread really does not care when you perform your task.
Callable : If you are trying to retrieve a value from a task, then use Callable. Now callable on its own will not do the job. You will need a Future that you wrap around your Callable and get your values on future.get (). Here the calling thread will be blocked till the Future comes back with results which in turn is waiting for Callable's call() method to execute.
So think about an interface to a target class where you have both Runnable and Callable wrapped methods defined. The calling class will randomly call your interface methods not knowing which is Runnable and which is Callable. The Runnable methods will execute asynchronously, till a Callable method is called. Here the calling class's thread will block since you are retrieving values from your target class.
NOTE : Inside your target class you can make the calls to Callable and Runnable on a single thread executor, making this mechanism similar to a serial dispatch queue. So as long as the caller calls your Runnable wrapped methods the calling thread will execute really fast without blocking. As soon as it calls a Callable wrapped in Future method it will have to block till all the other queued items are executed. Only then the method will return with values. This is a synchronization mechanism.
I found this in another blog that can explain it a little bit more these differences:
Though both the interfaces are implemented by the classes who wish to execute in a different thread of execution, but there are few differences between the two interface which are:
Callable<V>
instance returns a result of type V
, whereas a Runnable
instance doesn't.Callable<V>
instance may throw checked exceptions, whereas a Runnable
instance can'tThe designers of Java felt a need of extending the capabilities of the Runnable
interface, but they didn't want to affect the uses of the Runnable
interface and probably that was the reason why they went for having a separate interface named Callable
in Java 1.5 than changing the already existing Runnable
.
As it was already mentioned here Callable is relatively new interface and it was introduced as a part of concurrency package. Both Callable and Runnable can be used with executors. Class Thread (that implements Runnable itself) supports Runnable only.
You can still use Runnable with executors. The advantage of Callable that you can send it to executor and immediately get back Future result that will be updated when the execution is finished. The same may be implemented with Runnable, but in this case you have to manage the results yourself. For example you can create results queue that will hold all results. Other thread can wait on this queue and deal with results that arrive.
Runnable (vs) Callable comes into point when we are using Executer framework.
ExecutorService is a subinterface of Executor
, which accepts both Runnable and Callable tasks.
Earlier Multi-Threading can be achieved using Interface Runnable
Since 1.0, but here the problem is after completing the thread task we are unable to collect the Threads information. In-order to collect the data we may use Static fields.
Example Separate threads to collect each student data.
static HashMap<String, List> multiTasksData = new HashMap();
public static void main(String[] args) {
Thread t1 = new Thread( new RunnableImpl(1), "T1" );
Thread t2 = new Thread( new RunnableImpl(2), "T2" );
Thread t3 = new Thread( new RunnableImpl(3), "T3" );
multiTasksData.put("T1", new ArrayList() ); // later get the value and update it.
multiTasksData.put("T2", new ArrayList() );
multiTasksData.put("T3", new ArrayList() );
}
To resolve this problem they have introduced Callable<V>
Since 1.5 which returns a result and may throw an exception.
Single Abstract Method : Both Callable and Runnable interface have a single abstract method, which means they can be used in lambda expressions in java 8.
public interface Runnable {
public void run();
}
public interface Callable<Object> {
public Object call() throws Exception;
}
There are a few different ways to delegate tasks for execution to an ExecutorService.
execute(Runnable task):void
crates new thread but not blocks main thread or caller thread as this method return void.submit(Callable<?>):Future<?>
, submit(Runnable):Future<?>
crates new thread and blocks main thread when you are using future.get().Example of using Interfaces Runnable, Callable with Executor framework.
class CallableTask implements Callable<Integer> {
private int num = 0;
public CallableTask(int num) {
this.num = num;
}
@Override
public Integer call() throws Exception {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
return num;
}
}
class RunnableTask implements Runnable {
private int num = 0;
public RunnableTask(int num) {
this.num = num;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
}
}
public class MainThread_Wait_TillWorkerThreadsComplete {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Main Thread start...");
Instant start = java.time.Instant.now();
runnableThreads();
callableThreads();
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.format("Time taken : %02d:%02d.%04d \n", between.toMinutes(), between.getSeconds(), between.toMillis());
System.out.println("Main Thread completed...");
}
public static void runnableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> f1 = executor.submit( new RunnableTask(5) );
Future<?> f2 = executor.submit( new RunnableTask(2) );
Future<?> f3 = executor.submit( new RunnableTask(1) );
// Waits until pool-thread complete, return null upon successful completion.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
public static void callableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<Integer> f1 = executor.submit( new CallableTask(5) );
Future<Integer> f2 = executor.submit( new CallableTask(2) );
Future<Integer> f3 = executor.submit( new CallableTask(1) );
// Waits until pool-thread complete, returns the result.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
}
Source: Stackoverflow.com