多線程協作需解決:「線程間如何傳遞信號/數據」與「如何協調執行順序」。Java 提供三種層層遞進的機制。
多線程持有同一物件鎖,透過鎖的互斥性實現隱式通訊:
public class MyObject {
synchronized public void methodA() { /*...*/ }
synchronized public void methodB() { /*...*/ }
}
// ThreadA 呼叫 methodA(), ThreadB 呼叫 methodB()
// 同一物件鎖下,B 必須等 A 釋放鎖才能執行
本質:共享變量 + 鎖同步。簡單但靈活性低,難以表達複雜協作條件。
線程 B 不斷迴圈檢查條件(如 list.size() == 5),條件滿足則行動:
while (true) {
if (list.size() == 5) { /* 行動 */ break; }
}
缺點:佔用 CPU 空轉(「忙等待」),浪費資源;響應有延遲。
Object 基礎方法,配合 synchronized 使用:
wait():釋放鎖,進入等待集合,阻塞直到被喚醒或超時。notify():喚醒一個等待線程,重新競爭鎖。notifyAll():喚醒所有等待線程。// 共享鎖物件
Object lock = new Object();
// 消費者線程
synchronized (lock) {
while (list.size() != 5) { // 必須用 while 防止虛假喚醒
lock.wait(); // 釋放鎖、阻塞
}
// 條件滿足,繼續執行
}
// 生產者線程
synchronized (lock) {
for (int i = 0; i < 10; i++) {
list.add("elem");
if (list.size() == 5) lock.notify(); // 通知消費者
Thread.sleep(1000);
}
}
IllegalMonitorStateException。Condition / CountDownLatch 等高階工具。JDK 1.5+ java.util.concurrent 提供更強大工具:
BlockingQueue:生產消費首選,內建阻塞與同步。CountDownLatch、CyclicBarrier、Phaser:協調多線程階段。Lock + Condition:可支援多條件隊列、可中斷鎖。CompletableFuture、Parallel Streams:聲明式併發。理解 wait/notify 底層機制有助於排查併發 Bug,但實戰中優先使用 JUC 高階組件,減少低層次同步錯誤。