Difference Between Runnable and Callable

Naveen AnamaneniUpdated · 3 min read

Runnable and Callable both describe a task that can run on another thread. Runnable has a run() method that returns nothing and can't throw checked exceptions. Callable<V> has a call() method that returns a value and may throw any exception. Runnable dates from Java 1.0; Callable was added in Java 5 with the Executor framework. In this lesson, you will compare them side by side.

Example: The Same Job Both Ways

Let's see an example that counts the vowels in a name, once as a Runnable and once as a Callable.

RunnableVsCallable.java▶ Try it
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
 
public class RunnableVsCallable {
    static int vowels(String s) {
        return (int) s.toLowerCase().chars()
                      .filter(c -> "aeiou".indexOf(c) >= 0).count();
    }
 
    public static void main(String[] args) throws Exception {
        try (ExecutorService pool = Executors.newSingleThreadExecutor()) {
            AtomicInteger holder = new AtomicInteger();
            Runnable r = () -> holder.set(vowels("Anamaneni"));
            pool.submit(r).get();
            System.out.println("Runnable stored: " + holder.get());
 
            Callable<Integer> c = () -> vowels("Anamaneni");
            Future<Integer> f = pool.submit(c);
            System.out.println("Callable returned: " + f.get());
 
            Callable<String> reader = () -> {
                throw new java.io.IOException("file not found");
            };
            try {
                pool.submit(reader).get();
            } catch (java.util.concurrent.ExecutionException e) {
                System.out.println("Callable threw: " + e.getCause());
            }
        }
    }
}
Output
Runnable stored: 5
Callable returned: 5
Callable threw: java.io.IOException: file not found

Explanation: The Runnable can't return its answer, so it stores it in a shared AtomicInteger. The Callable simply returns it, and the result arrives through the Future. The last Callable throws a checked IOException, which a Runnable couldn't do without wrapping it.

Differences Between Runnable and Callable

RunnableCallable<V>
Packagejava.langjava.util.concurrent
IntroducedJava 1.0Java 5
Methodvoid run()V call() throws Exception
Returns a resultNoYes
Checked exceptionsCan't throw themCan throw them
Run by a plain ThreadYes: new Thread(runnable)No: needs an executor or FutureTask
Submitted to an executorexecute or submitsubmit, invokeAll, invokeAny

Which One Is a Lambda?

Common Mistakes

Passing a Callable to new Thread(...). It doesn't compile; wrap it in a FutureTask or use an executor.

Using a shared variable to get a result from a Runnable. Use a Callable and its Future instead.

Interview Corner

What is the difference between Runnable and Callable?

Runnable.run() returns void and can't throw checked exceptions; it can be run by a Thread or an executor. Callable<V>.call() returns a value of type V and can throw checked exceptions; it's submitted to an ExecutorService, which returns a Future<V> for the result or the failure. Use Callable whenever the task produces a result or may fail with a checked exception.

Practice

  1. Easy: Rewrite a Runnable that prints a square number as a Callable<Integer> that returns it.
  2. Harder: Wrap a Callable in a FutureTask, run it with a plain Thread, and read the result from the FutureTask.

Quick check: Runnable vs Callable

4 questions
1Which returns a value?
2Which can throw a checked exception directly?
3Can you pass a Callable to new Thread(...)?
4Which package is Callable in?

Key Takeaways

Was this tutorial helpful?

Lesson 415 of 482