The Difference Between the Runnable and Callable Interfaces in Java

The difference between the Runnable and Callable interfaces in Java

See explanation here.

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.

Where to use callable and where to use Runnable Interface?

Before there was the java.util.concurrent package, which landed in the Java 5 release, there was really no other options to doing concurrent computation, but to directly manipulate Threads.

You could manipulate threads directly, e.g. by subclassing:

public class MyThread extends Thread {
public void run() {
myComputation();
}
}

Or you could do the same by creating a Runnable, which was the preferred way (mainly because you do not need to subclass anything, which provides a clear separation of concern, better code reuse or generally, a better composition):

public class MyRunnable implements Runnable {
public void run() {
mycomputation();
}
}
new Thread(new MyRunnable()).start();

But no matter which way you used, you had to create, launch, manipulate, join on threads. Which has drawbacks: how many threads can you create? Is this expensive? (At some point, it is, although it became cheaper and cheaper with each JVM implementation.)

Plus, this API itself has limitations that the developer had to overcome: what if I want to return a value from a Runnable, seeing the signature does not allow it anyway? How can I know if my Runnable failed with an Exception? There things such as exception handlers and the like to allow for that with threads, but it was quiet a repetitive, error prone, task.

Enters the java.util.concurrent package! It offers an answer to all this (and more)!

You want to reuse threads for more than one "unit of work" (be it a Runnableor not?): you can. Want to know if the "unit of work" completed or failed: you can. Want to return a value: you can. Want to dynamically prioritize some tasks above others? Sure. Need the ability to schedule tasks? Can do. And so on.

Replace your Runnables with Callables (this is simple as can be, both are single method interfaces!), stop manipulating Threads in favor of Futures and leave the plumbing to ExecutorService.

My doubt is if Callable is capable of doing everything that Runnable, why so many people use Runnable instead of callable?

Maybe they do have old code (Java 1.4?). Maybe they are not aware of the benefits of the higher level abstractions, and prefer the low level Thread stuff?

Generally speaking, there is absolutely no reason to prefer using Threads since the concurrent API came.

Are there any extra overheads in implementing Callable interface in comparison with Runnable Interface?

In "implementing Callable" vs Runnable, no there is none. But there is a cost to the new Callable stuff because internally, it all comes back down to Threads and Runnables (at least, the current implementations do this). But you might actually gain performance, because of new capabilities like easier thread reuse!

So, yes, the concurrent API has its cost, but it is absolutely, completely negligible in any standard use case, but it also has new strengths that make it better in many ways, including performance.

Plus, you get massive new possibilities from the API, as already stated (see the Fork/Join framework, see the parallel streams in Java 8, ...), and reduce the need for any kink of "custom", "self made" concurrency code for said functionalities, which is notoriously hard to get right.

The benefit/cost ratio completely favors the "new" concurrent API.

How does java differentiate Callable and Runnable in a Lambda?

See the documentation of ExecutorService which has 2 submit methods with one parameter:

  • submit(Callable<T> task) using Callable<T> which has method call() returning T.
  • submit(Runnable task) usnig Runnable which has method run() returning nothing (void).

Your lambda gives an output, returns something:

executorService.submit(() -> {
System.out.println("Starting");
int n = new Random().nextInt(4000);
// try-catch-finally omitted
return n; // <-- HERE IT RETURNS N
});

So the lambda must be Callable<Integer> which is a shortcut for:

executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("Starting");
int n = new Random().nextInt(4000);
// try-catch-finally omitted
return n;
}}
);

To compare, try the same with Runnable and you see it's method's return type is void.

executorService.submit(new Runnable() {
@Override
public void run() {
// ...
}}
);

When should prefer Callable over Runnable and why?

Callable has two differences. It can return a value or throw a checked exception.

This make a difference when using lambdas so that even though you don't specify which one to sue the compiler has to work it out.

// the lambda here must be a Callable as it returns an Integer
int result = executor.submit(() -> return 2);

// the lambda here must be a Runnable as it returns nothing
executors.submit(() -> System.out.println("Hello World"));

// the lambda here must be a Callable as an exception could be thrown
executor.submit(() -> {
try (FileWriter out = new FileWriter("out.txt")) {
out.write("Hello World\n");
}
return null; // Callable has to return something
});

Callable vs Supplier interface in java

Their difference in usage can be seen from their respective documentation:

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
.

Supplier:

Represents a supplier of results.

There is no requirement that a new or distinct result be returned each
time the supplier is invoked.

This means that the caller of Callable.call expects an exception to be thrown and will handle the exception accordingly. This is useful for tasks like reading and writing to files, where many kinds of IOExceptions can be thrown. Callable is also designed to be run on another thread.

Supplier on the other hand, is very general. It just "supplies a value" and that's it.

So Callable is more specialised than Supplier. If you are not dealing with another thread or your task is very unlikely to throw an exception, Supplier is recommended.

Shall Callable be preferred over Runnable?

Both have their uses, and both are supported by the Executor framework in java.util.concurrent. Runnable has been around longer, but it is still in use and not discouraged.

Callables can throw exceptions and return values, which makes them the better abstraction for result-bearing tasks (such as fetching a resource from the network, performing an expensive computation of a value, and the like) [from Java Concurrency in Practice by Goetz, Bloch et. al., the standard work on Java concurrency].

So, if you are designing an API, I would suggest using Callables when possible. If you are sure that the tasks will not return values and will not throw exceptions, then Runnables are also a valid choice. There is no black and white here, especially because Runnables can easily be wrapped in Callables and vice versa.

As an aside, note that your Callable implementation need not declare throws Exception; the fact that Callable itself declares it is only to allow implementors to throw any checked exceptions. Callers of your Callable who rely solely on the Callable interface will have to write exception handling code, though.

Also note that Callables need not return a value; you can simply declare your Callable to return Void (with capital 'V').

Theory - Can we consider a callable PHP being a runnable?

It is my understanding that a callable represents some form of data the php interprets to be a method invocation. It does not mean that a callable has immediately executable code, java's does.

PHP will then take what parameters it has and goes and FINDS the code and executes it. I think that is the biggest difference. Sometimes there is immediately executable code, sometimes it has to lookup where the code is "\someclass::somestaticmethod"

My thoughts.



Related Topics



Leave a reply



Submit