Swing 作為單執行緒圖形工具包,其核心機制——事件分發執行緒(Event Dispatch Thread,EDT)決定了介面的響應性與線程安全。許多開發者將耗時業務邏輯直接寫在事件監聽器中,導致介面凍結,誤以為是 Swing 效能問題。本文系統梳理 EDT 運作原理、同步/非同步機制、invokeLater/invokeAndWait 正確用法,並對比生產者/消費者模型,幫助開發者建立正確的執行緒認知。
invokeAndWait)。invokeLater、事件發佈)。事件佇列即「傳送帶」:
invokeLater、定時器、網路回呼)。take() → dispatch()。wait()/notifyAll() 協調生產與消費速率。public class SyncQueue {
private final List queue = new LinkedList<>();
private final Object LOCK = new Object();
public T pop() {
synchronized (LOCK) {
while (queue.isEmpty()) {
try { LOCK.wait(); } catch (InterruptedException ignored) {}
}
return queue.remove(0);
}
}
public void push(T e) {
synchronized (LOCK) {
queue.add(e);
LOCK.notifyAll();
}
}
}
EDT 為單一消費者,終生循環於「等待事件 → 分發處理」。兩大特性:
invokeLater 讓呼叫執行緒立即返回。鐵律:
SwingUtilities.isEventDispatchThread() 驗證)。SwingWorker、線程池)。| 方法 | 模式 | 返回時機 | 典型用途 |
|---|---|---|---|
invokeLater(Runnable) | 非同步 | 立即返回,不等待執行完成 | UI 狀態更新、日誌記錄、觸發重繪 |
invokeAndWait(Runnable) | 同步 | 阻塞呼叫執行緒,直到 EDT 執行完畢 | 從 UI 元件安全讀取資料(如 JSlider.getValue()) |
public static void invokeAndWait(Runnable r) throws InterruptedException, InvocationTargetException {
if (EventQueue.isDispatchThread()) {
throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
}
Object lock = new Object(); // 專用鎖
InvocationEvent event = new InvocationEvent(Toolkit.getDefaultToolkit(), r, lock, true);
synchronized (lock) {
Toolkit.getEventQueue().postEvent(event); // 入隊
lock.wait(); // 阻塞當前執行緒
}
// 檢查異常傳播...
}
為何禁止在 EDT 呼叫? 若在 EDT 內調用,會將事件入隊後 wait() 釋放鎖,但 EDT 自身被阻塞,永無法從佇列取出該事件執行 → 經典死鎖(雙向等待)。Swing 故意拋出 Error 阻斷此誤用。
繞過佇列順序,直接在當前繪製請求中插入優先繪製,屬於「破壞 FIFO」的緊急繪製手段,慎用。
JDK 6+ 內建 SwingWorker 封裝背景任務與 EDT 互動:
SwingWorker worker = new SwingWorker<>() {
@Override protected Void doInBackground() {
// 耗時運算,定期 publish(進度)
return null;
}
@Override protected void process(List chunks) {
// EDT 更新進度條
}
@Override protected void done() {
// EDT 完成後處理
}
};
worker.execute();
推薦參考陳維雷博客《SwingWorker 詳解》三部曲,涵蓋取消、進度、異常處理等進階主題。
單執行緒存取模式可推廣至任何非線程安全庫:將共享資源存取限制在單一執行緒,即可免除鎖開銷與同步複雜度。桌面端請求量遠小於伺服端,單執行緒序列化足以應對,保證了事件順序的可預測性——這正是 Swing 選擇單執行緒模型的架構智慧。