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

Swing 執行緒安全完全指南:單一執行緒規則、事件分派與 SwingWorker 實戰

     編輯:Java 程式設計入門

核心哲學:為什麼 Swing 不支援多執行緒存取?

Swing 設計目標為強大、靈活、易用,且便於開發者擴充元件。為達成此目標,Swing 不要求元件支援多執行緒存取,而是採用單一執行緒規則:所有可能影響已實現(realized)元件狀態的代碼,必須在事件分派執行緒(Event Dispatch Thread, EDT)中執行。這消除了複雜的同步化問題,簡化元件開發。

關鍵定義

  • 實現:元件的 paint() 方法已被或可能被呼叫。頂層視窗呼叫 setVisible(true)、show()、pack() 時實現;加入已實現容器也會實現。
  • 事件分派執行緒 (EDT):執行繪圖(paint())與事件處理(actionPerformed())的專屬執行緒。亦可透過 SwingUtilities.invokeLater() 將代碼排入 EDT 執行。

單一執行緒規則與例外

規則

一旦 Swing 元件被實現,所有影響或依賴其狀態的代碼必須在 EDT 執行。

例外(線程安全方法)

  • API 文件標註 This method is thread safe, although most Swing methods are not. 的方法。
  • JComponent 的 repaint()、revalidate()、invalidate() 可從任何執行緒安全呼叫。
  • 主執行緒中建構 GUI(尚未實現前)是安全的;pack() 實現元件後,show() 應在 EDT 執行,但緊接著無其他 GUI 代碼實際上安全。
  • Applet 在 init() 中建構 GUI 安全(瀏覽器不會在 init()/start() 前繪製),但不得在其中呼叫 show()/setVisible(true)。

跨執行緒存取 GUI 的標準模式

1. SwingUtilities.invokeLater() / invokeAndWait()

// 非阻塞,排入 EDT 隊列尾端
SwingUtilities.invokeLater(() -> {
    label.setText("Updated from background thread");
});

// 阻塞,等待 EDT 執行完畢
SwingUtilities.invokeAndWait(() -> {
    // 需立即看到結果的操作
});

2. SwingWorker:長時間任務的最佳拍檔

用於耗時計算或 I/O 操作,避免阻塞 EDT 導致介面凍結。

SwingWorker<Void, Integer> worker = new SwingWorker<>() {
    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 0; i <= 100; i++) {
            Thread.sleep(50); // 模擬耗時任務
            publish(i); // 發送進度到 EDT
        }
        return null;
    }
    @Override
    protected void process(List<Integer> chunks) {
        progressBar.setValue(chunks.get(chunks.size() - 1)); // EDT 更新 UI
    }
    @Override
    protected void done() {
        JOptionPane.showMessageDialog(null, "完成!");
    }
};
worker.execute();

3. Timer:定期在 EDT 執行任務

Timer timer = new Timer(1000, e -> {
    label.setText("Time: " + new Date()); // 在 EDT 執行
});
timer.start();

總結

掌握「單一執行緒規則」、善用 invokeLater、SwingWorker、Timer,即能編寫線程安全、回應迅速的 Swing 應用程式。

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