多線程操作共享資源時,需協調執行順序。Java 提供 wait()、notify()、notifyAll() 實現線程間通信,必須在 同步塊 中調用,且鎖對象必須一致。
wait():釋放鎖,進入等待隊列(等待池)notify():喚醒一個等待線程,進入鎖池競爭鎖notifyAll():喚醒所有等待線程Object 中,因為鎖屬於對象共享對象 People 包含姓名、性別與標記位 myLock。輸入線程寫入,輸出線程讀取,通過 wait/notify 實現嚴格交替。
/** 共享資源對象 */
class People {
String name;
String sex;
boolean myLock = false; // false: 可寫入,true: 可讀取
}
/** 生產者:輸入線程 */
class PeopleJoin implements Runnable {
private People resource;
public PeopleJoin(People resource) { this.resource = resource; }
@Override
public void run() {
boolean flag = true;
while (true) {
synchronized (resource) { // 必須同步於共享對象
// 等待條件:資源被佔用(myLock=true)
if (resource.myLock) {
try { resource.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
// 寫入數據
if (flag) {
resource.name = "taoshihan";
resource.sex = "nan";
} else {
resource.name = "陶士涵";
resource.sex = "男";
}
flag = !flag;
// 狀態翻轉,喚醒消費者
resource.myLock = true;
resource.notify();
}
}
}
}
/** 消費者:輸出線程 */
class PeopleOut implements Runnable {
private People resource;
public PeopleOut(People resource) { this.resource = resource; }
@Override
public void run() {
while (true) {
synchronized (resource) {
// 等待條件:資源未就緒(myLock=false)
if (!resource.myLock) {
try { resource.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
// 讀取並打印
System.out.println(resource.name + "=====" + resource.sex);
// 狀態翻轉,喚醒生產者
resource.myLock = false;
resource.notify();
}
}
}
}
/** 測試啟動 */
public class ThreadDemo {
public static void main(String[] args) {
People resource = new People();
new Thread(new PeopleJoin(resource)).start();
new Thread(new PeopleOut(resource)).start();
}
}

控制台交替輸出英文與中文姓名性別,驗證協作正確。
synchronized(resource) 同一把鎖java.util.concurrent 包提供 BlockingQueue、CountDownLatch、Semaphore 等更高級協作工具,實際開發優先考慮此模式是「單生產單消費、單緩衝槽」模型。擴展為多生產多消費、有界緩衝區時,建議直接使用 ArrayBlockingQueue 等現成組件,避免手動管理鎖與條件的錯誤風險。