Google Guava 為 Java 標準庫的 Future 接口提供了強大的擴展,核心在於 ListenableFuture 接口及其配套的 Futures 靜態工具類。這些工具讓開發者能夠以聲明式風格編寫非阻塞異步代碼,避免傳統 Future.get() 造成的線程阻塞。
ListenableFuture 繼承自 JDK 的 Future,新增了 addListener(Runnable, Executor) 方法,允許在異步計算完成時自動觸發回調。Guava 進一步封裝了更方便的 Futures.addCallback() 方法,支援成功與失敗兩種回調場景:
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {
@Override
public void onSuccess(Object result) {
System.out.printf("計算成功: %s%n", result);
}
@Override
public void onFailure(Throwable thrown) {
System.out.printf("計算失敗: %s%n", thrown.getMessage());
}
}, executor);
ListenableFuture 的結果進行轉換,支援同步與異步(AsyncFunction)兩種模式。allAsList,但失敗/取消的 Future 在結果列表中以 null 佔位,不拋出異常。ListenableFuture 轉為 CheckedFuture,其 get() 方法拋出受檢異常,便於在業務邏輯中統一異常處理。Future 包裝為 ListenableFuture,實現舊代碼平滑遷移。@Test
public void testFuturesComposition() throws Exception {
ListeningExecutorService service = MoreExecutors.listeningDecorator(
Executors.newFixedThreadPool(10)
);
ListenableFuture<Integer> future1 = service.submit(() -> {
Thread.sleep(1000);
System.out.println("Task 1 done");
return 1;
});
ListenableFuture<Integer> future2 = service.submit(() -> {
Thread.sleep(1000);
System.out.println("Task 2 done");
return 2;
});
// 等待兩個任務全部完成
ListenableFuture<List<Integer>> all = Futures.allAsList(future1, future2);
// 異步轉換結果
ListenableFuture<String> transformed = Futures.transformAsync(all, results ->
Futures.immediateFuture(String.format("成功完成 %d 個任務", results.size()))
, service);
// 註冊最終回調
Futures.addCallback(transformed, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("最終結果: " + result);
}
@Override
public void onFailure(Throwable t) {
System.err.println("流程失敗: " + t.getMessage());
}
}, service);
// 阻塞等待演示(實際生產中應避免)
System.out.println(transformed.get());
}
ListeningExecutorService 提交任務,直接獲得 ListenableFuture。transformAsync 進行異步鏈式調用,避免阻塞線程。allAsList(強一致性)或 successfulAsList(部分容錯)。ListeningExecutorService 釋放線程資源。