0
0
JavaComparisonBeginner · 4 min read

Runnable vs Callable in Java: Key Differences and Usage

Runnable is a functional interface for tasks that do not return a result and cannot throw checked exceptions, while Callable allows returning a result and throwing checked exceptions. Both are used to run code in threads, but Callable is preferred when you need a result or exception handling.
⚖️

Quick Comparison

This table summarizes the main differences between Runnable and Callable interfaces in Java.

FeatureRunnableCallable
Return Typevoid (no result)Generic type (returns a result)
Exception HandlingCannot throw checked exceptionsCan throw checked exceptions
Methodrun()call()
Introduced InJava 1.0Java 5
UsageFor tasks without resultFor tasks with result or exceptions
Used WithThread, ExecutorServiceExecutorService
⚖️

Key Differences

Runnable is a simple interface with a single method run() that does not return any value and cannot throw checked exceptions. It is mainly used for tasks that perform actions without needing to return a result or report errors explicitly.

On the other hand, Callable has a call() method that returns a value of a generic type and can throw checked exceptions. This makes it suitable for tasks where you want to get a result back or handle exceptions properly.

Another difference is in usage: Runnable can be executed by a Thread directly, while Callable requires an ExecutorService to submit the task and get a Future representing the result.

💻

Runnable Code Example

java
public class RunnableExample implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable task is running");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new RunnableExample());
        thread.start();
    }
}
Output
Runnable task is running
↔️

Callable Equivalent

java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableExample implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "Callable task result";
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new CallableExample());
        try {
            String result = future.get();
            System.out.println(result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}
Output
Callable task result
🎯

When to Use Which

Choose Runnable when your task does not need to return any result and does not throw checked exceptions. It is simpler and can be used directly with Thread.

Choose Callable when you need to get a result from the task or handle checked exceptions properly. It works with ExecutorService and returns a Future to retrieve the result asynchronously.

In modern Java concurrent programming, prefer Callable for tasks requiring results or error handling, and use Runnable for simple fire-and-forget tasks.

Key Takeaways

Runnable runs code without returning a result or throwing checked exceptions.
Callable runs code that returns a result and can throw checked exceptions.
Runnable can be used with Thread; Callable requires ExecutorService and returns a Future.
Use Callable when you need a result or exception handling from a task.
Use Runnable for simple tasks that just run without feedback.