首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SwingWorker 實戰:讓 Swing GUI 不再凍結的非同步任務範例

     編輯:Java 相關知識

單執行緒規則下的正確背景處理姿勢

Swing 事件派發執行緒(EDT)負責所有 UI 更新,若在 EDT 執行耗時操作(網路、資料庫、大量運算),介面會凍結。SwingWorker<T,V> 是 Java 6+ 提供的標準解決方案:在背景執行緒執行 doInBackground(),透過 publish()/process() 安全推送中間結果至 EDT 更新 UI,done() 完成最終收尾。

範例功能速覽

  • 點擊「開始」啟動 10 秒累加任務(每秒累加 1~10)。
  • 即時顯示「累加 i 等於 sum」於文字區。
  • 進度條同步更新(0%~100%)。
  • 點擊「停止」取消任務,彈窗提示。
  • 完成顯示「完了。總計 55」。

核心 API 生命週期

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()

關鍵限制與陷阱

  1. 一次性物件:SwingWorker 只能 execute() 一次,不可重複啟動。需重新 new 實例。
  2. 泛型含義:SwingWorker<T, V>,T = 最終結果型別(get() 回傳),V = 中間進度型別(publish(V...) 參數)。
  3. 取消語意:cancel(true) 會中斷 sleep/wait 並設定 isCancelled()=true,需在迴圈中主動檢查並跳出。
  4. 例外處理:doInBackground 拋出的異常會被包裝在 ExecutionException 中,於 done() 的 get() 重拋。

現代替代方案

JavaFX 使用 Task/Service;Spring Boot 整合 @Async + CompletableFuture 處理後端非同步,前端透過 WebSocket/Server-Sent Events 推送進度。但 Swing 維護專案中,SwingWorker 仍是最輕量、零依賴的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved