Swing 事件派發執行緒(EDT)負責所有 UI 更新,若在 EDT 執行耗時操作(網路、資料庫、大量運算),介面會凍結。SwingWorker<T,V> 是 Java 6+ 提供的標準解決方案:在背景執行緒執行 doInBackground(),透過 publish()/process() 安全推送中間結果至 EDT 更新 UI,done() 完成最終收尾。
SwingWorker<Integer, int[]> sw = new SwingWorker<>() {
// 1. 背景執行緒:耗時運算,不可直接操作 UI 元件
@Override protected Integer doInBackground() {
int sum = 0;
for (int i = 1; i <= 10; i++) {
if (isCancelled()) break;
sum += i;
publish(new int[]{i, sum}); // → 觸發 process()
setProgress(i * 10); // → 觸發 PropertyChangeListener
Thread.sleep(1000);
}
return sum; // → 供 done() 取得
}
// 2. EDT 執行:處理 publish 傳來的中間結果批次
@Override protected void process(List<int[]> chunks) {
for (int[] v : chunks) taOutput.append("累加" + v[0] + "=" + v[1] + "\n");
}
// 3. EDT 執行:任務結束(正常/取消/異常)統一收尾
@Override protected void done() {
try { taOutput.append("完了。總計" + get() + "\n"); }
catch (InterruptedException|ExecutionException ignored) {}
}
};
// 進度條綁定
sw.addPropertyChangeListener(e -> {
if ("progress".equals(e.getPropertyName()))
progressBar.setValue((Integer)e.getNewValue());
});
sw.execute(); // 非同步啟動,切勿直接呼叫 run()
SwingWorker 只能 execute() 一次,不可重複啟動。需重新 new 實例。SwingWorker<T, V>,T = 最終結果型別(get() 回傳),V = 中間進度型別(publish(V...) 參數)。cancel(true) 會中斷 sleep/wait 並設定 isCancelled()=true,需在迴圈中主動檢查並跳出。doInBackground 拋出的異常會被包裝在 ExecutionException 中,於 done() 的 get() 重拋。JavaFX 使用 Task/Service;Spring Boot 整合 @Async + CompletableFuture 處理後端非同步,前端透過 WebSocket/Server-Sent Events 推送進度。但 Swing 維護專案中,SwingWorker 仍是最輕量、零依賴的選擇。