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 returns a result and may throw an exception. It is similar to Runnable, but more flexible since it can return a value and throw checked exceptions.
- Executes a task and returns a result using the call() method
- Can throw checked exceptions during execution
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 result of an asynchronous computation. When you submit a Callable or Runnable task to an ExecutorService, it returns a Future object.
- Stores the result of an asynchronous computation
- Provides methods like get() to retrieve the result and isDone() to check completion
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 |