When a task submitted to an ExecutorService throws, calling get() on its Future does not rethrow that exception directly; it wraps it inside an ExecutionException whose getCause holds the real failure.
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<Integer> future = pool.submit(() -> {
throw new ArithmeticException("task failed");
});
try {
future.get();
} catch (ExecutionException e) {
System.out.println(e.getClass().getSimpleName() + " caused by " + e.getCause().getClass().getSimpleName() + ": " + e.getCause().getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
pool.shutdown();
}
ExecutionException caused by ArithmeticException: task failed
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-09-27