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:
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
Here, the run()
method is executed in a separate thread.
Example 2: Using Runnable with ExecutorService
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:
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
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
.
Using FutureTask (Runnable + Callable)
If we need both Runnable and Callable behaviors, use FutureTask<T>
.FutureTask
allows combining Runnable
execution with Callable
result handling.
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?