Callable<V> 與 Future<V> 是 Java 5 引入的非同步計算核心介面,解決 Runnable **無回傳值、無法拋檢查例外** 的限制,配合 ExecutorService 實現任務提交、結果獲取、取消、超時控制。
| 特性 | Runnable | Callable<V> |
|---|---|---|
| 方法簽名 | void run() | V call() throws Exception |
| 回傳值 | 無 | 泛型 V |
| 拋檢查例外 | 不可 | 可 |
| 提交後拿到 | 無 (或自行共享物件) | Future<V> |
get():阻塞等待結果,可拋 InterruptedException, ExecutionException。get(timeout, unit):帶超時,超時拋 TimeoutException。cancel(mayInterruptIfRunning):嘗試取消,true 表示執行中也中斷。isDone() / isCancelled():狀態查詢。import java.util.concurrent.*;
public class CallableFutureDemo {
// 1. 立即完成任務
static class FastTask implements Callable<String> {
@Override public String call() { return "FastTask done"; }
}
// 2. 長時間運行任務 (可中斷)
static class LongTask implements Callable<String> {
@Override public String call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.println("LongTask working... " + i);
Thread.sleep(500);
}
return "LongTask finished";
}
}
// 3. 會拋出例外的任務
static class BadTask implements Callable<String> {
@Override public String call() { throw new RuntimeException("Intentional error"); }
}
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
// 提交任務
Future<String> f1 = es.submit(new FastTask());
Future<String> f2 = es.submit(new LongTask());
Future<String> f3 = es.submit(new BadTask());
try {
// 立即拿結果
System.out.println("f1: " + f1.get());
// 等待 2 秒後取消長任務
Thread.sleep(2000);
System.out.println("Cancel f2: " + f2.cancel(true)); // true = 中斷執行中線程
System.out.println("f2 cancelled? " + f2.isCancelled());
// 取得會拋例外的任務結果
System.out.println("f3: " + f3.get()); // 拋 ExecutionException 包裝 RuntimeException
} catch (InterruptedException | ExecutionException e) {
System.err.println("Task error: " + e.getCause().getMessage());
} finally {
es.shutdownNow(); // 關閉線程池
}
}
}
f1: FastTask done
LongTask working... 0
LongTask working... 1
LongTask working... 2
LongTask working... 3
Cancel f2: true
f2 cancelled? true
Task error: Intentional error
ExecutorService es = Executors.newFixedThreadPool(10);
CompletionService<Result> cs = new ExecutorCompletionService<>(es);
for (Task t : tasks) cs.submit(t);
for (int i = 0; i < tasks.size(); i++) {
Future<Result> f = cs.take(); // 阻塞直到有任務完成
process(f.get());
}
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");
CompletableFuture<String> combined = f1.thenCombine(f2, (a, b) -> a + b);
System.out.println(combined.join()); // "AB"
ExecutorService,避免互相影響。new ThreadPoolExecutor(..., new LinkedBlockingQueue<>(1000), ...) 防止 OOM。future.get(5, TimeUnit.SECONDS) 避免無限阻塞。ExecutionException.getCause() 取得真實業務例外。finally { executor.shutdown(); } 或使用 try-with-resources (Java 19+ ExecutorService 實作 AutoCloseable)。