🍄 博客搬家:第一版發佈於 2016/04/15 20:31java
🌺 原博客地址:https://my.oschina.net/sunqinwen/blog/660881設計模式
本實例中單獨爲生產者和消費者各開闢一個線程做爲生產者和消費者的執行線程,在生產者消費者設計模式中存在一個數據緩衝區,使生產者和消費者的「生產」和「消費」動做都在該緩衝區進行,這樣作的目的就是保證了生產者和消費者的完美解耦,試想一下若是沒了這個緩衝區,生產者和消費者中的方法互調,那麼兩個類的關聯度(耦合度)就會很高,一旦一個發生變化,勢必會影響另一個;ide
下面開始咱們的實例:this
首先是生產者的代碼:spa
/** * 生產者 */ public class Product implements Runnable{ private Queue queue; public Product(Queue queue){ this.queue = queue; } @Override public void run() { try{ for(int i = 0; i < 10; i++){ queue.product("Product------" + "No." + i);//開始生產 } }catch (Exception e){ e.printStackTrace(); } } }
這是消費者:.net
/** * 消費者 */ public class Consumer implements Runnable{ private Queue queue; public Consumer(Queue queue){ this.queue = queue; } @Override public void run() { try{ for(int i = 0; i < 10; i++){ System.out.println("already gone : " + queue.consumer());//開始消費 } }catch (Exception e){ e.printStackTrace(); } } }
這是緩衝區,幾乎全部的邏輯都是在這裏實現的:線程
/** * 隊列緩衝區 */ public class Queue { private Object signal = new Object();//當前線程的掛起和執行標記 private boolean isFull = false;//隊列是否已滿 private List list = new ArrayList<>();//隊列 public void product(String msg) throws Exception{ synchronized (signal){ if(!isFull){//若是沒有滿,執行以下代碼 list.add(msg);//加進隊列 isFull = true; System.out.println("Product One !"); signal.notify();//喚醒當前消費者裏面被掛起的線程 } signal.wait();//不然,若是當前滿了,說明消費者正在消費,掛起當前生產線程 } } public String consumer() throws Exception{ synchronized (signal){ if(!isFull){ //不滿,說明生產者正在生產,應當掛起consumer線程 System.out.println("Empty Product !"); signal.wait(); } isFull = false;//已消費,隊列被標記爲不滿狀態 signal.notify();//通知生產者 } //消費(讀取) String result = ""; if(list.size() > 0){ result = this.list.get(list.size() - 1); this.list.remove(list.size() - 1); } return result; } }
上面這個模式利用java現有的阻塞隊列很容易實現,能夠避免上述代碼中很大一部分代碼(線程的掛起、喚醒、隊列彈出數據等)設計