在多線程編程中,線程之間的同步是一個非常重要的問題。Java提供了多種機制來實現線程同步,其中”等待-通知”機制是一種非常常用的方式。本文將詳細介紹Java中的”等待-通知”機制,并通過示例代碼展示其使用方法。
“等待-通知”機制是一種線程間通信的方式,它允許一個線程在某個條件不滿足時進入等待狀態,直到另一個線程通知它條件已經滿足。這種機制通常用于解決生產者-消費者問題、線程池管理等場景。
在Java中,”等待-通知”機制主要通過Object
類的wait()
、notify()
和notifyAll()
方法來實現。這些方法必須在同步代碼塊或同步方法中調用,因為它們依賴于對象的監視器鎖。
wait()
、notify()
和notifyAll()
方法wait()
方法wait()
方法使當前線程進入等待狀態,直到其他線程調用該對象的notify()
或notifyAll()
方法,或者指定的超時時間到達。調用wait()
方法時,當前線程會釋放對象的監視器鎖,允許其他線程獲取鎖并執行。
wait()
方法有以下幾個重載版本:
wait()
:使當前線程無限期等待,直到被通知。wait(long timeout)
:使當前線程等待指定的毫秒數,或者直到被通知。wait(long timeout, int nanos)
:使當前線程等待指定的毫秒數加納秒數,或者直到被通知。notify()
方法notify()
方法喚醒在該對象上等待的單個線程。如果有多個線程在等待,JVM會選擇一個線程進行喚醒。被喚醒的線程將嘗試重新獲取對象的監視器鎖,并在獲取鎖后繼續執行。
notifyAll()
方法notifyAll()
方法喚醒在該對象上等待的所有線程。所有被喚醒的線程將競爭對象的監視器鎖,獲取鎖的線程將繼續執行。
下面通過一個簡單的生產者-消費者問題來演示如何使用”等待-通知”機制。
生產者-消費者問題是一個經典的多線程同步問題。生產者線程負責生產數據并將其放入緩沖區,消費者線程負責從緩沖區中取出數據并進行處理。當緩沖區滿時,生產者線程需要等待;當緩沖區空時,消費者線程需要等待。
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
private static final int BUFFER_SIZE = 5;
private final Queue<Integer> buffer = new LinkedList<>();
private final Object lock = new Object();
public void produce() throws InterruptedException {
int value = 0;
while (true) {
synchronized (lock) {
while (buffer.size() == BUFFER_SIZE) {
lock.wait(); // 緩沖區滿,生產者等待
}
System.out.println("生產者生產: " + value);
buffer.add(value++);
lock.notifyAll(); // 通知消費者
}
Thread.sleep(1000); // 模擬生產時間
}
}
public void consume() throws InterruptedException {
while (true) {
synchronized (lock) {
while (buffer.isEmpty()) {
lock.wait(); // 緩沖區空,消費者等待
}
int value = buffer.poll();
System.out.println("消費者消費: " + value);
lock.notifyAll(); // 通知生產者
}
Thread.sleep(1000); // 模擬消費時間
}
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producerThread = new Thread(() -> {
try {
pc.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread consumerThread = new Thread(() -> {
try {
pc.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producerThread.start();
consumerThread.start();
}
}
buffer
是一個Queue
,用于存儲生產者生產的數據。lock
是一個Object
,用于同步生產者和消費者線程。produce()
方法中,生產者線程在緩沖區滿時調用lock.wait()
進入等待狀態,直到消費者線程消費數據后調用lock.notifyAll()
喚醒它。consume()
方法中,消費者線程在緩沖區空時調用lock.wait()
進入等待狀態,直到生產者線程生產數據后調用lock.notifyAll()
喚醒它。notifyAll()
方法用于喚醒所有等待的線程,確保生產者和消費者都能及時響應。wait()
、notify()
和notifyAll()
方法必須在同步代碼塊或同步方法中調用,否則會拋出IllegalMonitorStateException
異常。wait()
方法時,通常需要在循環中檢查條件,以防止虛假喚醒(spurious wakeup)。notify()
方法只會喚醒一個等待的線程,而notifyAll()
方法會喚醒所有等待的線程。根據具體場景選擇合適的喚醒方式。Java中的”等待-通知”機制是一種強大的線程同步工具,能夠有效地解決多線程環境下的資源競爭和線程間通信問題。通過合理使用wait()
、notify()
和notifyAll()
方法,可以實現復雜的線程同步邏輯,確保程序的正確性和高效性。
在實際開發中,理解并掌握”等待-通知”機制的使用方法,對于編寫高效、可靠的多線程程序至關重要。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。