傳統 Runnable 的 run() 方法無返回值且無法拋出受檢異常,Java 5 引入 Callable<V> 接口,其 call() 方法支持泛型返回值與異常拋出,完美解決異步任務結果獲取難題。
Future<V> 代表異步計算的結果,提供五大核心能力:
get():阻塞獲取結果,支持超時控制cancel(boolean):嘗試取消任務執行isDone() / isCancelled():狀態查詢FutureTask<V> 實現 RunnableFuture<V>(繼承 Runnable 和 Future),既可作為任務提交給執行器,又可作為結果容器:
// 方式一:配合 ExecutorService ExecutorService executor = Executors.newCachedThreadPool(); FutureTask<Integer> futureTask = new FutureTask<>(new Task()); executor.submit(futureTask); // 方式二:直接用 Thread 執行 Thread thread = new Thread(futureTask); thread.start(); // 統一獲取結果 Integer result = futureTask.get();
當需要提交一組 Callable 任務並按完成順序獲取結果時,ExecutorCompletionService 是最佳選擇:
ExecutorService pool = Executors.newFixedThreadPool(10);
CompletionService<Integer> cs = new ExecutorCompletionService<>(pool);
for (int i = 0; i < 10; i++) {
final int seq = i;
cs.submit(() -> {
Thread.sleep(new Random().nextInt(5000));
return seq;
});
}
for (int i = 0; i < 10; i++) {
System.out.println(cs.take().get()); // 按完成順序取出
}
Runnable (void run())
↑
Callable<V> (V call() throws Exception)
↑
RunnableFuture<V> extends Runnable, Future<V>
↑
FutureTask<V> implements RunnableFuture<V>
ExecutorService.submit(Callable) 簡化代碼get(timeout, unit) 避免無限阻塞InterruptedExceptionCompletableFuture 實現更豐富的異步組合