Difference between Runnable and Callable Interface in Java?
RunnableCallable
Defines a task that can be executed by a threadSimilar to Runnable, but it is intended to yield a value.
Contains one method run() which holds the logic that will be executed by the threadContains one method call() which holds the logic that will be executed by the thread.
Can throw checked exceptions.
Returns a value which can be used for further processing.
Can be used to check the status of the task, wait for it to complete and retrieve the result of the task.
Allows cancellation of the task if it is not finished yet.
Both Runnable and Callable interfaces can be utilised to generate and launch threads in a Java program.

Runnable Example

class RunnableTask implements Runnable {
    public void run() {
        System.out.println("Running Runnable Task");
    }
}

public class Main {
    public static void main(String[] args) {
        RunnableTask task = new RunnableTask();
        Thread thread = new Thread(task);
        thread.start();
    }
}

This will output “Running Runnable Task”.

Callable Example

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;

class CallableTask implements Callable<String> {
    public String call() throws Exception {
        System.out.println("Running Callable Task");
        return "Task Complete";
    }
}

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

This will output “Running Callable Task” and “Task Complete” when the program is executed.

  • The CallableTask class implements the Callable interface and overrides the call() method.
  • The return type of call() method is String.
  • The submit() method of ExecutorService is used to submit the task for execution and it returns an object of Future representing the result of the task.
  • And the get() method is used to retrieve the result of the task.

Final Note – How to choose between Runnable and Callable?

Generally, if you need to perform a computation that returns a value, throws checked exceptions, or requires extra control over the execution of the thread, it’s optimal to use the Callable interface. Conversely, if you just need to run a basic task in a separate thread, the Runnable interface is perhaps the prime choice.

📚 Further Reading & Related Topics

If you’re exploring the difference between Runnable and Callable interfaces in Java, these related articles will provide deeper insights:

• Threads in Java: The Difference Between Calling Start and Run Methods – Learn about thread management and how Runnable and Callable integrate with thread execution in Java.

• Java 16 and the Standardization of Records: Simplifying Data Classes – Explore how modern Java features like records and functional programming complement the usage of concurrency utilities such as Runnable and Callable.

Leave a comment

I’m Sean

Welcome to the Scalable Human blog. Just a software engineer writing about algo trading, AI, and books. I learn in public, use AI tools extensively, and share what works. Educational purposes only – not financial advice.

Let’s connect