Future<T> 是 Java 並發套件中表示「異步計算結果」的核心介面。它將「提交任務」與「獲取結果」解耦,讓主線程在等待耗時操作期間能繼續處理其他邏輯。
public String downloadContents(URL url) throws IOException {
try (InputStream input = url.openStream()) {
return IOUtils.toString(input, StandardCharsets.UTF_8);
}
}
// 呼叫端:主線程卡在這裡,直到下載完成
String contents = downloadContents(new URL("https://example.com"));
public Future<String> startDownloading(URL url) {
return executor.submit(() -> {
try (InputStream input = url.openStream()) {
return IOUtils.toString(input, StandardCharsets.UTF_8);
}
});
}
// 呼叫端:立即返回 Future,主線程可做其他事
Future<String> future = startDownloading(new URL("https://example.com"));
// ... 其他計算 ...
String contents = future.get(); // 需要時再阻塞等待
| 方法 | 語義 | 關鍵行為 |
|---|---|---|
get() | 阻塞等待結果 | 計算完成前一直阻塞;若任務拋出異常,包裝為 ExecutionException |
get(timeout, unit) | 帶超時等待 | 超時拋出 TimeoutException,避免無限等待 |
isDone() | 非阻塞檢查完成狀態 | 返回 true 表示結果可用(含正常、異常、取消) |
cancel(mayInterruptIfRunning) | 嘗試取消任務 | false:僅取消未啟動任務;true:嘗試中斷正在運行的任務 |
isCancelled() | 檢查是否被取消 | 任務正常完成前被取消返回 true |
Future<String> future = startDownloading(url);
while (!future.isDone()) {
askUserToWait(); // 更新 UI
doSomeComputation(); // 做其他有用工作
}
String result = future.get(); // 此時不會阻塞
避免忙等待:isDone() 配合 Thread.sleep() 或 CompletableFuture 回調更佳。
future.cancel(true); // 嘗試中斷正在運行的任務
mayInterruptIfRunning=false:任務未啟動則取消;已啟動則讓其繼續運行至完成mayInterruptIfRunning=true:對正在運行的任務發送中斷信號(Thread.interrupt())關鍵點:只有任務代碼正確響應中斷(拋出/處理 InterruptedException),取消才真正生效。常見可中斷操作:Thread.sleep()、Object.wait()、Condition.await()、Future.get()、I/O 通道操作等。
ExecutorService pool = Executors.newFixedThreadPool(10);
Future<String> future = pool.submit(new Callable<String>() {
@Override public String call() { /* 耗時計算 */ }
});
// Spring @Async
@Async
public Future<String> startDownloading(URL url) {
return new AsyncResult<>(downloadContent(url));
}
// EJB @Asynchronous
@Asynchronous
public Future<String> startDownloading(URL url) { ... }
框架層面由容器管理線程池、代理方法調用,業務代碼專注邏輯。
| 局限 | Java 8+ 解決方案 |
|---|---|
| 無法鏈式組合多個非同步操作 | CompletableFuture 支援 thenApply/thenCompose/thenCombine |
| 無法註冊完成回調 | whenComplete/exceptionally |
阻塞式 get() 易造成線程浪費 | 非阻塞組合式 API,適合反應式編程 |
| 異常處理分散 | 統一異常傳播機制 |
Future 是 Java 非同步編程的基石抽象,理解其語義、取消機制、與執行器的協作關係至關重要。現代應用建議優先使用 CompletableFuture 或反應式流框架,但在維護舊代碼、對接傳統 API 時,Future 仍是核心介面。