繼承 Thread、實作 Runnable 之外,Java 提供 Callable<V> 介面作為第三種建立執行緒方式。其 call() 方法支援回傳值與拋出檢查型例外,配合 Future<V> 與 CompletionService<V> 實現更強大的非同步程式設計模式。
public class CallableFutureDemo {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
// 提交 Callable 任務,獲得 Future
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(20); // 模擬耗時運算
return "hi, amos";
}
});
// 同步等待結果(阻塞直到完成)
System.out.println("結果: " + future.get());
// 可設定超時等待
// future.get(1, TimeUnit.MILLISECONDS);
executor.shutdown();
}
}
submit() 而非 execute() 提交任務call() 回傳值型別必須與 Future<V> 泛型一致Future 提供 cancel()、isDone()、isCancelled() 等控制方法CompletionService 專為批量提交 Callable 任務設計,其 take() 方法會阻塞直到下一個完成的任務可用,類似「哪塊麥田先熟收割哪塊」。
public class CompletionServiceDemo {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletionService<Integer> service = new ExecutorCompletionService<>(executor);
// 提交 10 個隨機耗時任務
for (int i = 0; i < 10; i++) {
final int taskId = i;
service.submit(() -> {
Thread.sleep(new Random().nextInt(3000));
return taskId;
});
}
// 依完成順序獲取結果
for (int i = 0; i < 10; i++) {
System.out.println("已完成任務: " + service.take().get());
}
executor.shutdown();
}
}
Future.get() 順序阻塞導致的效能損耗invokeAll() 批量提交並等待全部完成poll(timeout) 實現非阻塞輪詢get() 會拋出 ExecutionException 包裝任務異常finally 區塊關閉 ExecutorService