wait()、notify()、notifyAll() 定義在 Object.java 中:
wait():當前線程進入等待狀態,釋放持有的鎖,直到其他線程調用同對象的 notify() 或 notifyAll() 喚醒。notify():喚醒在此對象監視器上等待的單個線程。notifyAll():喚醒在此對象監視器上等待的所有線程。wait(long timeout)、wait(long timeout, int nanos)。// WaitTest.java
class ThreadA extends Thread {
public ThreadA(String name) { super(name); }
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " call notify()");
notify(); // 喚醒等待線程
}
}
}
public class WaitTest {
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
synchronized (t1) {
try {
System.out.println(Thread.currentThread().getName() + " start t1");
t1.start();
System.out.println(Thread.currentThread().getName() + " wait()");
t1.wait(); // 主線程等待
System.out.println(Thread.currentThread().getName() + " continue");
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
main start t1 main wait() t1 call notify() main continue
synchronized(t1) 獲取 t1 對象鎖。t1 後,主線程調用 t1.wait() 釋放鎖並進入等待。t1 運行,獲取 this 鎖,調用 notify() 喚醒主線程。t1 結束釋放鎖,主線程重獲鎖繼續執行。
JDK 文檔明確指出:wait() 讓「當前線程」等待。「當前線程」是正在 CPU 上運行的線程。雖然語法是 t1.wait(),但調用位置在主線程中,主線程必須是運行狀態才能執行該代碼,因此等待的是主線程。
// WaitTimeoutTest.java
class ThreadA extends Thread {
public ThreadA(String name) { super(name); }
public void run() {
System.out.println(Thread.currentThread().getName() + " run");
while (true); // 死循環,不喚醒主線程
}
}
public class WaitTimeoutTest {
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
synchronized (t1) {
try {
System.out.println(Thread.currentThread().getName() + " start t1");
t1.start();
System.out.println(Thread.currentThread().getName() + " call wait");
t1.wait(3000); // 等待 3 秒或被喚醒
System.out.println(Thread.currentThread().getName() + " continue");
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
// NotifyAllTest.java
public class NotifyAllTest {
private static Object obj = new Object();
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
ThreadA t2 = new ThreadA("t2");
ThreadA t3 = new ThreadA("t3");
t1.start(); t2.start(); t3.start();
try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (obj) {
System.out.println(Thread.currentThread().getName() + " notifyAll()");
obj.notifyAll(); // 喚醒 t1, t2, t3
}
}
static class ThreadA extends Thread {
public ThreadA(String name) { super(name); }
public void run() {
synchronized (obj) {
try {
System.out.println(Thread.currentThread().getName() + " wait");
obj.wait();
System.out.println(Thread.currentThread().getName() + " continue");
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
核心原因:它們依賴於「對象的同步鎖」。
wait() 讓線程等待並釋放鎖,否則其他線程無法獲取鎖進入同步塊調用 notify()。notify() 必須在持有「同一把鎖」的前提下調用,才能喚醒因該鎖而等待的線程。Object。