Java 物件內建的 wait()、notify()、notifyAll() 是執行緒協作的基石。本文系統整理這組底層 API、執行緒優先級與群組的實務觀點,並補充 Swing/AWT 事件派發執行緒(EDT)的跨執行緒 UI 更新技巧。
呼叫前必須持有該物件的鎖(在 synchronized 區塊或方法內)。
wait():釋放鎖,進入等待集合,直到 notify()/notifyAll() 喚醒Thread.interrupt() 中斷wait(long timeout))notify():隨機喚醒一個等待該物件的執行緒。notifyAll():喚醒所有等待該物件的執行緒。synchronized (lock) {
while (!condition) {
lock.wait();
}
// 執行關鍵區段
}
notifyAll()。僅在確定等待集合中所有執行緒條件相同、且喚醒任一個即可滿足後續邏輯時,才考慮 notify()(效能優化,風險較高)。java.util.concurrent 套件(BlockingQueue、CountDownLatch、Semaphore、ReentrantLock、Condition 等),JDK 1.5+ 已內建。Thread.setPriority(int) 範圍 1(MIN)~ 10(MAX),預設 5(NORM)。ThreadGroup 設計初衷為階層式管理,但功能薄弱(stop()、suspend()、resume() 已棄用)。uncaughtException(Thread t, Throwable e) — 可覆寫實作全域例外處理(記錄、重啟服務、關閉系統)。Thread 同等方法,不依賴 ThreadGroup。所有 Swing 元件建立、狀態變更、繪圖必須在事件派發執行緒(EDT)執行。
| 方法 | 行為 | 適用場景 |
|---|---|---|
invokeLater(Runnable) | 非阻塞,將任務排入 EDT 佇列稍後執行 | 背景執行緒觸發 UI 更新、記錄日誌、啟動對話框 |
invokeAndWait(Runnable) | 阻塞呼叫執行緒,直到 EDT 完成任務 | 需要取得 UI 回傳值、同步等待對話框關閉 |
void showHelloThereDialog() {
Runnable task = () -> JOptionPane.showMessageDialog(mainFrame, "Hello There");
SwingUtilities.invokeLater(task); // 非阻塞
}
java.awt.EventQueue.invokeLater/AndWait 功能相同,適用於純 AWT 專案。
| 主題 | 關鍵點 | 建議 |
|---|---|---|
| wait/notify | 需持有鎖、while 迴圈檢查條件、優先 notifyAll | 改用 java.util.concurrent 高階工具 |
| 優先級 | 平台相依、不可倚賴 | 保持預設,專注鎖設計 |
| ThreadGroup | 功能殘缺、僅 uncaughtException 有用 | 不使用,改用 Thread.setDefaultUncaughtExceptionHandler |
| SwingUtilities | EDT 單執行緒規則、invokeLater/AndWait | 所有跨執行緒 UI 操作必須委派 |
掌握 wait/notify 底層語意有助於理解高階並發工具原理,但實務開發請拥抱 java.util.concurrent。執行緒優先級與群組屬於「了解即可、勿深度依賴」範疇。Swing/AWT 開發者務必內化 EDT 規則,善用 SwingUtilities 避免競態條件與凍結介面。