Java Callable & Future
In this page:
What is Callable?
The Callable interface represents an asynchronous task, much like Runnable, but with two key differences: a Callable can return a computed value from its call() method, and it can throw checked exceptions during execution, which Runnable's run() cannot.
Example: What is Callable?
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
Callable<Integer> task = () -> {
if (false) throw new Exception("checked exception allowed");
return 5 * 5;
};
System.out.println(task.call());
}
}
Login to try C/C++/Java/PHP code in the editor
What is Future?
A Future represents the eventual, pending result of an asynchronous task submitted to an executor. You can poll it with isDone() to check completion status, or call get() to block until the result is ready and retrieve it.
Example: What is Future?
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> 100);
System.out.println(future.isDone());
System.out.println(future.get());
executor.shutdown();
}
}
Login to try C/C++/Java/PHP code in the editor
Handling Exceptions with Future
If a Callable task throws an exception during execution, that exception doesn't propagate immediately — it's captured by the framework and wrapped. When you later call Future.get(), it re-throws that failure wrapped in an ExecutionException, with the original exception available via getCause().
Example: Handling Exceptions with Future
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> { throw new RuntimeException("task failed"); });
try {
future.get();
} catch (ExecutionException e) {
System.out.println("Caught: " + e.getCause().getMessage());
}
executor.shutdown();
}
}
Login to try C/C++/Java/PHP code in the editor
Multiple Callables with invokeAll()
You can run multiple Callable tasks in parallel using an ExecutorService's invokeAll() method, which submits every task at once and blocks until all of them complete. It returns a List of Future objects in the same order the tasks were submitted, letting you retrieve each result individually.
Example: Multiple Callables with invokeAll()
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<Integer>> tasks = List.of(() -> 1 + 1, () -> 2 + 2, () -> 3 + 3);
List<Future<Integer>> results = executor.invokeAll(tasks);
for (Future<Integer> f : results) System.out.println(f.get());
executor.shutdown();
}
}
Login to try C/C++/Java/PHP code in the editor
Best Practices with Future
To keep your application from blocking indefinitely on a hung task, always pass a timeout to Future.get(timeout, unit) rather than calling the no-argument overload. It's also good practice to shut down every executor service inside a finally block so it's released even if a task throws.
Example: Best Practices with Future
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Future<Integer> future = executor.submit(() -> 42);
System.out.println(future.get(2, TimeUnit.SECONDS));
} catch (Exception e) {
System.out.println("Timed out or failed");
} finally {
executor.shutdown();
}
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: