Card 03/ 09

ComparisonDifficulty: Intermediate1 min

Runnable vs Callable

The two ways to describe a task, and the two things only one of them can hand back.

Runnable and Callable are the two interfaces that describe a task for a thread or a pool. Both have one method and both can be written as a lambda; they differ in the two things a method can produce: a value, and a checked exception. Submitting either to a pool returns a Future, a handle for a result that arrives later.

The two task interfaces
Compared onRunnableCallable<V>
The methodvoid run()V call() throws Exception
Returns a valueNoYes
May throw a checked exceptionNoYes
Submitting gives youFuture<?>, whose get() returns null when it completesFuture<V>, holding the result
Used byThread, execute, submitsubmit, invokeAll
java
Future<?> a = pool.submit(() -> log.info("done"));

Future<Long> b = pool.submit(() -> countRowsIn(file));

The compiler chooses between them from the lambda's body. Line 1 produces nothing, so it is a Runnable; line 3 produces a long, so it is a Callable. Nothing in the source says which.

The decision rule. If the task produces an answer somebody wants, or can fail in a way somebody should hear about, it is a Callable. Otherwise Runnable is fine. The exception matters most, because a Callable's exception reaches whoever collects its result.

Where an exception from a Runnable goes depends on how it was handed to the pool. Through submit, it is caught and stored in the returned Future, like a Callable's. Through execute, it reaches the thread's uncaught-exception handler, which by default prints it to standard error and nothing else.