在併發編程中,生產者-消費者(producer-consumer)是一個經典的問題;一個數據緩衝區,一個或多個生產者向這個緩衝區寫數據,一個或多個消費者從這個緩衝區中讀數據,緩衝區做爲線程共享資源,須要採用同步機制控制,好比使用synchronized關鍵字,可是咱們還須要更多的限制條件,好比當緩衝區滿時就不能在寫入數據,當緩衝區空時就不能在讀取數據;java
對於這種狀況,Javaz提供了wait() , notify()和notifyAll() 方法,這幾個方法都是Object對象的方法;一個線程只能在synchronized代碼塊中調用wait()方法,若是在synchronized代碼塊以外調用wait()方法,JVM將會拋出一個IllegalMonitorStateException異常;當一個線程調用wait()方法時,這個線程將會被休眠(sleep)而且釋放對以前鎖定的對象中的同步代碼塊,此時其它線程將有機會執行這個對象的同步代碼塊;當要喚醒這個線城時,能夠調用被鎖定對象的notify()或notifyAll()方法;編程
下面的實例中將會展現這幾個方法是如何使用的;併發
1. 建立一個EventStorage類ide
public class EventStorage { private int maxSize; private LinkedList<Date> storage; public EventStorage(){ maxSize=10; storage = new LinkedList<>(); } public synchronized void set() { while (storage.size() == maxSize) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } storage.offer(new Date()); System.out.printf("Set:%d\n",storage.size()); notifyAll(); } public synchronized void get() { while (storage.size() == 0) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("Get:%d: %s\n", storage.size(), storage.poll()); notifyAll(); } }2.分別建立生產者和消費者
public class Consumer implements Runnable { private EventStorage eventStorage; public Consumer(EventStorage eventStorage) { this.eventStorage = eventStorage; } @Override public void run() { for (int i = 0; i < 100; i++) { eventStorage.get(); } } }
public class Producer implements Runnable { private EventStorage eventStorage; public Producer(EventStorage eventStorage) { this.eventStorage = eventStorage; } @Override public void run() { for (int i = 0; i < 100; i++) { eventStorage.set(); } } }
public class Main { public static void main(String[] args) { EventStorage storage=new EventStorage(); Producer producer=new Producer(storage); Thread thread1=new Thread(producer); Consumer consumer=new Consumer(storage); Thread thread2=new Thread(consumer); thread2.start(); thread1.start(); } }