前面闡述了實現生產者與消費者問題的兩種方式:wait() / notify()方法 和 await() / signal()方法,本文繼續闡述多線程的經典問題---生產者與消費者的第三種方式:BlockingQueue阻塞隊列方法。java
BlockingQueue阻塞隊列方法多線程
BlockingQueue是JDK5.0的新增內容,它是一個已經在內部實現了同步的隊列,實現方式採用的是咱們第2種await() / signal()方法。它能夠在生成對象時指定容量大小。它用於阻塞操做的是put()和take()方法。函數
put()方法:相似於咱們上面的生產者線程,容量達到最大時,自動阻塞。測試
take()方法:相似於咱們上面的消費者線程,容量爲0時,自動阻塞。this
緩衝區(倉庫):spa
import java.util.concurrent.LinkedBlockingQueue; public class Storage { // 倉庫最大存儲量 private final int MAX_SIZE = 100; // 倉庫存儲的載體 private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>(100); // 生產num個產品 public void produce(int num){ // 若是倉庫剩餘容量爲MAX_SIZE if (list.size() == MAX_SIZE){ System.out.println("【庫存量】:" + MAX_SIZE + "暫時不能執行生產任務!"); } // 生產條件知足狀況下,生產num個產品 for (int i = 1; i <= num; ++i){ try{ // 放入產品,自動阻塞 list.put(new Object()); } catch (InterruptedException e){ e.printStackTrace(); } System.out.println("【現倉儲量爲】:" + list.size()); } } // 消費num個產品 public void consume(int num){ // 若是倉庫存儲量不足 if (list.size() == 0){ System.out.println("【庫存量】:0 暫時不能執行消費任務!"); } // 消費條件知足狀況下,消費num個產品 for (int i = 1; i <= num; ++i){ try{ // 消費產品,自動阻塞 list.take(); } catch (InterruptedException e){ e.printStackTrace(); } } System.out.println("【現倉儲量爲】:" + list.size()); } // set/get方法 public LinkedBlockingQueue<Object> getList() { return list; } public void setList(LinkedBlockingQueue<Object> list) { this.list = list; } public int getMAX_SIZE() { return MAX_SIZE; } }
生產者:線程
public class Producer extends Thread { // 每次生產的產品數量 private int num; // 所在放置的倉庫 private Storage storage; // 構造函數,設置倉庫 public Producer(Storage storage){ this.storage = storage; } // 線程run函數 public void run(){ produce(num); } // 調用倉庫Storage的生產函數 public void produce(int num){ storage.produce(num); } // get/set方法 public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; } }
消費者:code
public class Consumer extends Thread { // 每次消費的產品數量 private int num; // 所在放置的倉庫 private Storage storage; // 構造函數,設置倉庫 public Consumer(Storage storage){ this.storage = storage; } // 線程run函數 public void run(){ consume(num); } // 調用倉庫Storage的生產函數 public void consume(int num){ storage.consume(num); } // get/set方法 public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; } }
測試類:對象
public class Test { public static void main(String[] args) { // 倉庫對象 Storage storage = new Storage(); // 生產者對象 Producer p1 = new Producer(storage); Producer p2 = new Producer(storage); Producer p3 = new Producer(storage); Producer p4 = new Producer(storage); Producer p5 = new Producer(storage); Producer p6 = new Producer(storage); Producer p7 = new Producer(storage); // 消費者對象 Consumer c1 = new Consumer(storage); Consumer c2 = new Consumer(storage); Consumer c3 = new Consumer(storage); // 設置生產者產品生產數量 p1.setNum(10); p2.setNum(10); p3.setNum(10); p4.setNum(10); p5.setNum(10); p6.setNum(10); p7.setNum(80); // 設置消費者產品消費數量 c1.setNum(50); c2.setNum(20); c3.setNum(30); // 線程開始執行 c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); p4.start(); p5.start(); p6.start(); p7.start(); } }