同步調用阻塞線程,異步回調釋放線程做別的事。本文展示三種異步回調實現層次:經典 Future 模式(手工實現)、JDK 8 CompletableFuture(標準庫)、自定義回調接口(輕量級),附完整可運行代碼與場景選型建議。
| 角色 | 說明 | 對應代碼 |
|---|---|---|
| 調用者 | 發起請求、持有憑證、稍後獲取結果 | Main / Controller |
| 憑證 | 異步操作的句柄,提供獲取結果/取消/查狀態方法 | Future / CompletableFuture / CallbackToken |
| 真實數據 | 耗時運算產出的最終結果 | RealData / 返回值 |
| 執行者 | 在背景線程執行耗時任務 | Thread / ExecutorService |
// 1. 數據接口
interface Data { String getContent(); }
// 2. 真實數據:構造耗時
class RealData implements Data {
private final String content;
public RealData(int count, char c) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(c);
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
}
content = sb.toString();
}
public String getContent() { return content; }
}
// 3. 未來數據:憑證,同步等待真實數據就緒
class FutureData implements Data {
private RealData realData;
private boolean ready = false;
public synchronized void setRealData(RealData rd) {
if (ready) return; // 防重複設置
this.realData = rd;
ready = true;
notifyAll(); // 喚醒等待線程
}
public synchronized String getContent() {
while (!ready) {
try { wait(); } catch (InterruptedException ignored) {}
}
return realData.getContent();
}
}
// 4. 服務端:接收請求 → 返回憑證 → 後台構建真實數據
class Host {
public Data request(final int count, final char c) {
final FutureData future = new FutureData();
new Thread(() -> {
RealData real = new RealData(count, c);
future.setRealData(real);
}).start();
return future; // 立即返回憑證
}
}
// 5. 客戶端使用
public class FutureDemo {
public static void main(String[] args) {
Host host = new Host();
Data d1 = host.request(10, 'A');
Data d2 = host.request(20, 'B');
Data d3 = host.request(30, 'C');
System.out.println("主線程繼續做其他事...");
try { Thread.sleep(500); } catch (InterruptedException ignored) {}
System.out.println("d1: " + d1.getContent()); // 阻塞直到就緒
System.out.println("d2: " + d2.getContent());
System.out.println("d3: " + d3.getContent());
}
}
ExecutorService executor = Executors.newFixedThreadPool(4); public CompletableFuturesupplyAsync(int count, char c) { return CompletableFuture.supplyAsync(() -> { StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; i++) { sb.append(c); try { Thread.sleep(100); } catch (InterruptedException ignored) {} } return sb.toString(); }, executor); } // 使用:鏈式組合、異常處理、多任務編排 public void demo() { CompletableFuture f1 = supplyAsync(10, 'A'); CompletableFuture f2 = supplyAsync(20, 'B'); CompletableFuture f3 = supplyAsync(30, 'C'); // 並行等待所有完成,彙總結果 CompletableFuture.allOf(f1, f2, f3).thenRun(() -> { try { System.out.println("全部完成: " + f1.get() + ", " + f2.get() + ", " + f3.get()); } catch (Exception e) { throw new RuntimeException(e); } }); // 或:任一完成即處理 CompletableFuture.anyOf(f1, f2, f3).thenAccept(res -> System.out.println("最快完成: " + res)); }
// 1. 回調接口 interface Callback{ void onSuccess(T result); void onFailure(Throwable cause); } // 2. 請求載體 class Request { private final Callback callback; private final Supplier task; public Request(Supplier task, Callback callback) { this.task = task; this.callback = callback; } public void start() { new Thread(() -> { try { T result = task.get(); callback.onSuccess(result); } catch (Throwable t) { callback.onFailure(t); } }).start(); } } // 3. 使用 new Request<>(() -> { Thread.sleep(2000); return "異步結果"; }, new Callback () { public void onSuccess(String r) { System.out.println("成功: " + r); } public void onFailure(Throwable t) { t.printStackTrace(); } }).start(); System.out.println("主線程繼續...");
| 維度 | 手工 Future | CompletableFuture | 自定義回調 |
|---|---|---|---|
| API 豐富度 | 低 | 極高(組合、異常、超時、線程池) | 低 |
| 依賴 | 無 | JDK 8+ | 無 |
| 線程池管理 | 手工 | 內建/自定義 | 手工 |
| 回調地獄風險 | 中 | 低(鏈式) | 高(嵌套) |
| 適用場景 | 教學、極簡項目、JDK 7 以下 | **生產首選**、微服務、複雜編排 | 輕量級、Android 早期、嵌入式 |
new ThreadPoolExecutor(core, max, ..., new ArrayBlockingQueue<>(cap)),防止任務堆積 OOM。exceptionally()、handle() 統一處理,避免異常丟失。future.cancel(true) 配合任務內部 Thread.interrupted() 檢查實現響應式取消。future = null 或用弱引用。異步回調是高併發、響應式系統的基石。建議:新項目直接上 CompletableFuture,舊項目逐步遷移;僅在極度受限環境下考慮手工 Future 或自定義回調。