Careeroza
Callable and Future
Getting a Result Back
Runnable.run() returns nothing and cannot throw checked exceptions. Callable<V>.call() returns a value and can throw. submit(callable) returns a Future<V>: a handle to a result that will be ready later.
| Future method | Meaning |
|---|---|
get() | block until the result is ready |
get(timeout, unit) | block at most this long, else TimeoutException |
isDone() | finished (normally, with exception, or cancelled)? |
cancel(true) | try to cancel (interrupts if running) |
resultNow(), state() (Java 19) | non-blocking result / RUNNING, SUCCESS, FAILED, CANCELLED |
Fetching Prices in Parallel
Example
Three "slow" price services are called at the same time. Total time is about the slowest call, not the sum. Results are read in a fixed order.
import java.util.*;
import java.util.concurrent.*;
public class Main {
static int fetchPrice(String shop, int delayMs, int price) throws InterruptedException {
Thread.sleep(delayMs); // pretend network call
return price;
}
public static void main(String[] args) throws Exception {
try (ExecutorService pool = Executors.newFixedThreadPool(3)) {
Map<String, Future<Integer>> futures = new LinkedHashMap<>();
futures.put("Amazon", pool.submit(() -> fetchPrice("Amazon", 300, 1299)));
futures.put("Flipkart", pool.submit(() -> fetchPrice("Flipkart", 200, 1249)));
futures.put("Croma", pool.submit(() -> fetchPrice("Croma", 100, 1399)));
long start = System.nanoTime();
for (var e : futures.entrySet()) {
System.out.println(e.getKey() + ": Rs " + e.getValue().get());
}
long ms = (System.nanoTime() - start) / 1_000_000;
System.out.println("Parallel (under 600 ms): " + (ms < 600));
}
}
}Output
Amazon: Rs 1299 Flipkart: Rs 1249 Croma: Rs 1399 Parallel (under 600 ms): true
invokeAll and Exceptions
Example
An exception inside a task is stored in the Future and rethrown by get() wrapped in ExecutionException.
import java.util.*;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
List<Callable<String>> tasks = List.of(
() -> "report-A ready",
() -> { throw new IllegalStateException("DB down for report-B"); },
() -> "report-C ready");
try (ExecutorService pool = Executors.newFixedThreadPool(3)) {
for (Future<String> f : pool.invokeAll(tasks)) { // results in task order
try {
System.out.println(f.get());
} catch (ExecutionException e) {
System.out.println("Failed: " + e.getCause().getMessage());
}
}
}
}
}Output
report-A ready Failed: DB down for report-B report-C ready