Object.wait()、notify()、notifyAll() 是 Java 線程協作的基礎原語,必須在 synchronized 區塊/方法中調用。本範例模擬「駕駛等待乘客、乘客上車通知駕駛」場景,展示基本同步協作流程。
public class Road {
public static void main(String[] args) {
Car car = new Car();
new Thread(new Driver(car)).start();
new Thread(new Passenger(car)).start();
}
}
class Car {
synchronized public void waitForPassenger() {
try { wait(); } catch (InterruptedException e) {}
}
synchronized public void passengerArrived() {
notify(); // 喚醒單一等待線程 (此處只有駕駛)
}
}
class Driver implements Runnable {
private Car car;
public Driver(Car c) { this.car = c; }
public void run() {
while (true) {
System.out.println("駕駛等待乘客......");
car.waitForPassenger(); // 釋放鎖進入 WAITING
try { Thread.sleep(3000); } catch (InterruptedException e) {}
Thread.yield();
try { Thread.sleep(100); } catch (InterruptedException e) {}
car.passengerArrived(); // 模擬駕駛完成行程後通知下一輪? (邏輯略顯混淆)
System.out.println("乘客上車,駕駛出發");
}
}
}
class Passenger implements Runnable {
private Car car;
public Passenger(Car c) { this.car = c; }
public void run() {
while (true) {
Thread.yield();
try { Thread.sleep(3000); } catch (InterruptedException e) {}
System.out.println("一位乘客上車");
car.passengerArrived(); // 通知駕駛
System.out.println("駕駛停止等待,進入休眠...");
car.waitForPassenger(); // 乘客也進入等待? (邏輯混淆)
}
}
}
wait/notify 必須在同一物件鎖 (Car 實例) 的 synchronized 方法中調用。WAITING 狀態,直到被 notify/notifyAll 喚醒或中斷。原範例中駕駛與乘客雙方都呼叫 wait/notify,職責不清,易產生活鎖或邏輯混淆。標準生產者-消費者模型應為:
class Car {
private boolean hasPassenger = false;
synchronized public void waitForPassenger() {
while (!hasPassenger) { try { wait(); } catch (InterruptedException e) {} }
hasPassenger = false; // 乘客已上車,重置狀態
}
synchronized public void passengerArrived() {
hasPassenger = true;
notify(); // 或 notifyAll()
}
}
// Driver 呼叫 waitForPassenger() 循環載客
// Passenger 呼叫 passengerArrived() 送客
java.util.concurrent 高層組件 (BlockingQueue、Semaphore、CountDownLatch、CyclicBarrier、Lock/Condition) 替代底層 wait/notify。wait() 必須放在 while (condition) 循環中,防止虛假喚醒。notifyAll() 除非確定單一等待者且效能極度敏感。