在Java中,多線程的等待喚醒機(jī)制是一種非常重要的同步機(jī)制,它可以讓線程之間相互協(xié)作,確保多個(gè)線程能夠正確地共享資源,避免數(shù)據(jù)不一致和線程沖突等問(wèn)題。
等待喚醒機(jī)制主要包括兩個(gè)操作:等待(wait)和喚醒(notify)。在Java中,這兩個(gè)操作都是由Object類提供的,因此任何Java對(duì)象都支持等待喚醒機(jī)制。
一、等待操作
等待操作是通過(guò)調(diào)用對(duì)象的wait()方法實(shí)現(xiàn)的。當(dāng)一個(gè)線程調(diào)用對(duì)象的wait()方法時(shí),該線程會(huì)被放入到對(duì)象的等待集中,并釋放對(duì)象的鎖。其他線程可以獲取對(duì)象的鎖并執(zhí)行相關(guān)操作。
在調(diào)用wait()方法時(shí),必須先獲取對(duì)象的鎖。否則,會(huì)拋出IllegalMonitorStateException異常。通常,在調(diào)用wait()方法之前,需要先通過(guò)synchronized塊或方法來(lái)獲取對(duì)象的鎖。
二、喚醒操作
喚醒操作是通過(guò)調(diào)用對(duì)象的notify()方法或notifyAll()方法實(shí)現(xiàn)的。當(dāng)一個(gè)線程調(diào)用對(duì)象的notify()方法時(shí),會(huì)從對(duì)象的等待集中選擇一個(gè)線程喚醒,讓其獲取對(duì)象的鎖并執(zhí)行相關(guān)操作。如果調(diào)用notifyAll()方法,則會(huì)將對(duì)象等待集中的所有線程都喚醒。
同樣地,在調(diào)用notify()或notifyAll()方法之前,也需要先獲取對(duì)象的鎖。否則,會(huì)拋出IllegalMonitorStateException異常。
三、示例代碼
演示:
public class WaitWakeExample {
private Object lock = new Object();
private int count = 0;
public void incrementCount() {
synchronized (lock) {
while (count == 5) {
try {
// 等待喚醒
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println("Count: " + count);
// 喚醒其他線程
lock.notifyAll();
}
}
public void decrementCount() {
synchronized (lock) {
while (count > 0) {
try {
// 等待喚醒
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println("Count: " + count);
// 喚醒其他線程
lock.notifyAll();
}
}
}
incrementCount()和decrementCount()這兩個(gè)方法都會(huì)先檢查count的值,如果count不滿足條件,就會(huì)調(diào)用wait()方法進(jìn)入等待狀態(tài)。當(dāng)count滿足條件時(shí),就會(huì)調(diào)用notifyAll()方法喚醒所有等待的線程。這樣就可以保證多個(gè)線程能夠正確地共享count變量,避免數(shù)據(jù)不一致和線程沖突等問(wèn)題。