在現代軟體開發中,經常遇到長時間運行的操作,例如呼叫 Web Service、遠端 RPC、複雜運算等。若採用同步阻塞方式,會導致使用者介面凍結、響應中斷,嚴重影響使用者體驗。本文將介紹如何運用回調機制與多執行緒,實現非同步處理,讓耗時任務在背景執行,完成後再通知呼叫端,確保主程式流程暢通無阻。
傳統的循序執行模型中,呼叫者直接等待被呼叫者返回結果。而非同步回調模式將流程拆分為兩階段:呼叫者啟動任務後立即繼續執行;被呼叫者在獨立執行緒中完成工作,再透過持有的呼叫者參考,主動呼叫回調方法傳回結果。這種「好萊塢原則」——「別呼叫我們,我們會呼叫你」——有效解耦了雙方的生命週期。
public class Viewer {
private int count;
public Viewer(int count) { this.count = count; }
public void printNewCount(int newCount) {
System.out.println("New Count=" + newCount);
}
public int getCount() { return count; }
public void setCount(int count) { this.count = count; }
}
Viewer 扮演「介面」角色,持有初始資料,並提供 printNewCount 作為回調入口。
public class LongTimeResponse implements Runnable {
private Viewer viewer;
private int count;
public LongTimeResponse(Viewer viewer) {
this.viewer = viewer;
this.count = viewer.getCount();
calculateNewCount();
}
private void calculateNewCount() {
new Thread(this).start();
}
@Override
public void run() {
try { Thread.sleep(10000); }
catch (Exception ex) { ex.printStackTrace(); }
viewer.printNewCount(count * count * count);
}
}
建構子中即啟動新執行緒,run() 方法模擬 10 秒耗時運算,完成後呼叫 viewer.printNewCount() 回傳結果。
Viewer viewer = new Viewer(10);
LongTimeResponse longTimeResponse = new LongTimeResponse(viewer);
viewer.printNewCount(123);
輸出順序證明非同步特性:
New Count=123(主執行緒繼續執行)New Count=1000(背景執行緒完成回調)掌握「執行緒 + 回調」模式是 Java 非同步程式設計的基石。實務上可進一步引入 ExecutorService、CompletableFuture 或 Reactive Streams,構建更健壯的非同步系統。