Runnable & Callable
About
Runnable
and Callable
are two interfaces in Java used for executing tasks in separate threads. Both are commonly used in multithreading and concurrency but have differences in functionality.
Runnable Interface
Definition
Runnable
is an interface that represents a task to be executed by a thread.It has one method:
void run();
It does not return a result and cannot throw checked exceptions.
Usage
A Runnable
task can be executed by:
Creating a
Thread
objectUsing
ExecutorService
Example 1: Implementing Runnable using a Class
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Executing task in thread: " + Thread.currentThread().getName());
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable()); // Assign task to thread
thread.start(); // Starts a new thread
}
}
Here, the run()
method is executed in a separate thread.
Example 2: Using Runnable with ExecutorService
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RunnableWithExecutor {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new MyRunnable());
executor.shutdown();
}
}
ExecutorService
is a thread pool manager that efficiently manages threads.
Callable Interface
Definition
Callable<T>
is a functional interface introduced in Java 5.Unlike
Runnable
, it returns a result and can throw checked exceptions.It has one method:
T call() throws Exception;
The return type
T
allows it to be used for asynchronous computation.
Usage
A Callable
task is executed using an ExecutorService and returns a Future<T>
object.
Example 1: Implementing Callable with ExecutorService
import java.util.concurrent.Callable;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000); // Simulate delay
return "Task completed by " + Thread.currentThread().getName();
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable()); // Submit task
System.out.println("Waiting for result...");
String result = future.get(); // Blocks until the result is available
System.out.println("Result: " + result);
executor.shutdown();
}
}
Combining Runnable and Callable
If we want a Runnable but need a result, use Executors.callable().
This is useful when converting a Runnable
to Callable
.
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
public class RunnableToCallable {
public static void main(String[] args) {
Callable<Object> callableTask = Executors.callable(() ->
System.out.println("Runnable inside Callable"));
}
}
Using FutureTask (Runnable + Callable)
If we need both Runnable and Callable behaviors, use FutureTask<T>
.FutureTask
allows combining Runnable
execution with Callable
result handling.
import java.util.concurrent.FutureTask;
public class FutureTaskExample {
public static void main(String[] args) throws Exception {
FutureTask<String> futureTask = new FutureTask<>(() -> "Task completed!");
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("Result: " + futureTask.get());
}
}
Comparison Runnable and Callable
Introduced in
Java 1.0
Java 5
Method
void run()
T call() throws Exception
Return Value
No (void)
Yes (Generic T)
Exception Handling
Cannot throw checked exceptions
Can throw checked exceptions
Used With
Thread
, ExecutorService
ExecutorService
, Future
Best For
Executing tasks without result
Executing tasks that return a value
When to Use Runnable
vs Callable
vs Others
Runnable
vs Callable
vs OthersUse Case
Use
Why?
You need to execute a task without returning a result
Runnable
Runnable.run()
has a void
return type, making it ideal for simple background tasks.
You need to execute a task and return a result
Callable
Callable.call()
returns a value, allowing you to capture the task's output.
You need to execute a task but may need to check its completion later
Callable + Future
Future<T>
allows retrieving the result later without blocking the main thread.
You need to execute a task and get notified when it's completed
FutureTask
FutureTask
allows combining Runnable
and Callable
, and it can be used as a Future
.
You need to execute multiple independent tasks and wait for all to complete
ExecutorService + invokeAll()
invokeAll()
submits multiple Callable
tasks and waits for all results.
You need to execute multiple independent tasks and get the first completed result
ExecutorService + invokeAny()
invokeAny()
submits multiple Callable
tasks and returns the first successful result.
You need fine-grained control over thread execution (e.g., priority, interruption)
Thread + Runnable
Thread
can directly manage execution but is less flexible than thread pools.
You need to handle checked exceptions in a background task
Callable
Callable.call()
supports throwing checked exceptions.
You need to execute a task repeatedly at a fixed rate
ScheduledExecutorService
scheduleAtFixedRate()
and scheduleWithFixedDelay()
allow scheduled execution.
You need to execute CPU-intensive parallel tasks
ForkJoinPool
ForkJoinPool
supports work-stealing, ideal for recursive and parallel tasks.
You need to execute stream operations in parallel
Parallel Streams
stream().parallel()
splits work across multiple cores automatically.
You need to process a collection of tasks asynchronously
CompletableFuture
CompletableFuture
allows non-blocking execution and chaining tasks together.
You need to execute a task with a timeout
ExecutorService + Future.get(timeout)
Future.get(timeout, TimeUnit.SECONDS)
prevents indefinite waiting.
You need to execute a task in the background and monitor progress
CompletableFuture + thenApply/thenAccept
CompletableFuture
allows progress tracking and callbacks.
You need non-blocking, event-driven async execution
CompletableFuture + SupplyAsync()
Asynchronous execution without blocking threads.
Last updated
Was this helpful?