wait()、notify()、notifyAll() 是 Object 類的 final native 方法,無法被子類覆寫。這三個方法必須在同步方法或同步區塊(synchronized)中呼叫,且當前線程必須持有該物件的鎖,否則會拋出 IllegalMonitorStateException。
notify() 或 notifyAll() 喚醒由於這些方法定義在 Object 類中,可透過以下三種方式呼叫:
wait(); // 方式1
this.wait(); // 方式2
super.wait(); // 方式3
在 synchronized 方法外呼叫 wait() 會拋出異常:
public class ObjectWaitTest {
public static void main(String args[]) {
A a = new A();
try {
a.printThreadInfo(); // synchronized 方法
a.wait(); // 錯誤!不在 synchronized 區塊中
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
class A {
public synchronized void printThreadInfo() throws InterruptedException {
Thread t = Thread.currentThread();
System.out.println("ThreadID:" + t.getId() + ", ThreadName:" + t.getName());
}
}
執行結果:IllegalMonitorStateException
將 wait() 放入 synchronized 方法內部:
class A {
public synchronized void printThreadInfo() throws InterruptedException {
Thread t = Thread.currentThread();
System.out.println("ThreadID:" + t.getId() + ", ThreadName:" + t.getName());
this.wait(1000); // 正確:在 synchronized 方法中呼叫
}
}
主線程呼叫後,釋放鎖並等待 1000ms,其他線程可進入同步方法。
wait()/notify() 必須在 synchronized 方法或區塊內呼叫wait() 會釋放鎖,notify() 不釋放鎖(直到同步區塊結束)wait(long timeout) 可避免無限期等待造成死鎖