What is the difference between Runnable and Callable, and what is a Future?
Runnable.run returns nothing and cannot throw checked exceptions. Callable.call returns a value and may throw. Submitting a Callable to an ExecutorService gives a Future, a handle you use to fetch the result later.
Explain it simply
You send a friend to the market. With Runnable they just go and do it, and you never hear back. With Callable they come back with the vegetables, or with the reason they failed. The Future is the token slip you hold while waiting: you can check whether they are done, or wait for them.
Example
import java.util.concurrent.*;
ExecutorService pool = Executors.newSingleThreadExecutor();
Callable<Integer> task = () -> {
Thread.sleep(100); // allowed: call() may throw checked exceptions
return 6 * 7;
};
Future<Integer> result = pool.submit(task);
System.out.println(result.get()); // prints: 42 (blocks until ready)
System.out.println(result.isDone()); // prints: true
pool.shutdown();What to say in the interview
"Runnable has void run() with no checked exceptions. Callable<V> has V call() throws Exception. A Future lets me call get() to block for the result, get with a timeout, isDone to poll, or cancel. If the task threw, get() rethrows it wrapped in ExecutionException. For non-blocking chains, CompletableFuture is the better tool."
Common mistakes
- Calling get() immediately after submit for many tasks one by one, which removes the parallelism.
- Ignoring ExecutionException and losing the real cause.