In Java, multithreading allows tasks to run concurrently, improving performance and responsiveness. Traditionally, developers used the Runnable interface to define tasks, but it has two major limitations: it cannot return a result and cannot throw checked exceptions. To overcome these, Java introduced the Callable and Future interfaces in Java 5.
- Callable executes a task and returns a result with exception handling
- Future represents the result of a Callable task and retrieves it later
Callable Interface
The Callable interface represents a task that can return a result and throw checked exceptions. It is an alternative to Runnable when a task needs to produce an output.
- Defines the call() method for task execution
- Allows checked exceptions during execution
- Commonly used with Future to retrieve results
import java.util.concurrent.*;
public class CallableExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
int sum = 0;
for (int i = 1; i <= 5; i++) sum += i;
return sum; // returns result
};
Future<Integer> future = executor.submit(task);
System.out.println("Result: " + future.get());
executor.shutdown();
}
}
Output
Result: 15
Explanation: A Callable task is submitted to the executor. It calculates the sum of numbers from 1 to 5 and returns the result. The result is retrieved using future.get() after the task finishes.
Future Interface
The Future interface represents the outcome of an asynchronous task and allows you to interact with it after submission to an ExecutorService.
- Acts as a handle to track task status
- get() retrieves the result (blocks until completion)
- isDone() checks if the task has finished
import java.util.concurrent.*;
public class CallableFutureExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> 10 + 20);
try {
Integer result = future.get(); // waits but returns instantly
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Output
Result: 30
Explanation: This code creates a single-thread executor to run a task asynchronously using Callable. The task calculates the sum of 10 and 20, and the result is stored in a Future object. Using future.get(), the program retrieves the result (30), and finally shuts down the executor to free resources.
Callable vs Future
Table showing difference between callable and future.
| Feature | Callable | Future |
|---|---|---|
| Purpose | Represents a task that returns a result | Represents the result of an asynchronous task |
| Return Type | Returns a result when executed | Holds the result returned by a Callable |
| Defined In | java.util.concurrent package | java.util.concurrent package |
| Execution | Submitted to ExecutorService | Returned by ExecutorService.submit() |
| Methods | Has one method call() | Has methods like get(), isDone(), cancel() |
| Exception Handling | Can throw checked exceptions | Handles results and exceptions after execution |
| Usage | Defines what to execute | Controls, monitors, and retrieves the result of a task |