在併發編程中的一個經典問題是生產者與消費者問題:咱們有一個數據緩衝區,一個或多個數據的生產者在緩衝區存儲數據,而一個或多個數據的消費者,把數據從緩衝區取出。java
因爲緩衝區是一個共享的數據結構,咱們必須採用同步機制,好比 synchronized 關鍵字來控制對它的訪問。可是咱們有更多的限制因素,若是緩衝區是滿的,生產者不能存儲數據,若是緩衝區是空的,消費者不能取出數據。編程
對於這些類型的狀況,Java在Object對象中提供wait(),notify(),和notifyAll() 方法的實現。緩存
wait() 方法:數據結構
一、只能在同步代碼塊中調用併發
二、當一個線程調用 wait() 方法,jvm將這個線程置入休眠,而且釋放控制這個同步代碼快的對象,同時容許其餘線程執行這個對象控制的其餘同步代碼塊jvm
三、爲了喚醒這個線程,必須在這個對象控制的某個同步代碼快調用 notify() 方法或者 notifyAll() 方法ide
import java.util.Date; import java.util.concurrent.LinkedBlockingQueue; /** * 中間緩存 */ public class EventStorage { private int maxSize; private LinkedBlockingQueue<Date> storage; public EventStorage(int maxSize){ this.maxSize = maxSize; storage = new LinkedBlockingQueue<Date>(); } // 存放操做 public synchronized void set(){ // 在while循環中,你必須保持檢查條件和調用wait()方法。你不能繼續執行,直到這個條件爲true。 while(storage.size() == maxSize){ //循環判斷 爲 真,才進行 線程 掛起操做. try { wait(); // 掛起 該線程,等待 剩餘空間出現 } catch (InterruptedException e) { e.printStackTrace(); } } storage.offer(new Date()); System.out.println("存操做- storage size:" + storage.size()); notifyAll(); // 喚醒 全部 由於 wait() 操做而休眠的 線程. } // 取出操做 public synchronized void get(){ while(storage.size() == 0){ //循環判斷 爲 真,才進行 線程 掛起操做. try { wait(); // 掛起 該線程,等待 剩餘空間出現 } catch (InterruptedException e) { e.printStackTrace(); } } storage.poll(); System.out.println("取出操做- storage size:" + storage.size()); notifyAll(); // 喚醒 全部 由於 wait() 操做而休眠的 線程. } }
import java.util.concurrent.TimeUnit; /** * 生產者 */ public class EventProducer implements Runnable{ private EventStorage eventStorage; public EventProducer(EventStorage eventStorage){ this.eventStorage = eventStorage; } @Override public void run() { while(true){ eventStorage.set(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }
/** * 消費者 */ public class EventCustomer implements Runnable{ private EventStorage eventStorage; public EventCustomer(EventStorage eventStorage){ this.eventStorage = eventStorage; } public void run() { while(true){ eventStorage.get(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }
public class EventTest { public static void main(String[] args) { EventStorage eventStorage = new EventStorage(3); EventProducer producer = new EventProducer(eventStorage); EventCustomer customer = new EventCustomer(eventStorage); Thread threadProducer = new Thread(producer); Thread threadCostomer = new Thread(customer); threadProducer.start(); threadCostomer.start(); } }