問題描述:一個生產者在生產產品,這些產品將提供給若干個消費者去消費,爲了使生產者和消費者可以併發執行,在二者之間設置一個具備多個緩衝區的緩衝池,生產者將生產的產品放入一個緩衝區內,消費者能夠從緩衝區中取走產品進行消費;緩存
生產者和消費者必須保持同步,不容許消費者到一個空的緩衝區中取產品,也不容許生產者向一個已經投放了產品的緩衝區再次投放產品;併發
代碼實現:函數
1).wait()和notify()方式來實現this
public class Storage{ //緩衝區最大承載量 private final int MAX_SIZE = 100; //緩衝區存儲的載體 private LinkedList<Object> list = new LinkedList<Object>(); /** * * 生產num個產品 */ public void produce(int num){ //獲取鎖 synchronized(list){ //緩存區剩餘容量不足 while(list.size() + num > MAX_SIZE){ System.out.println("要生產的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行生產任務!"); try{ //因爲條件不知足,生產阻塞 list.wait() }catch(InterruptedException e){ e.printStackTrace(); } } //在生產條件知足狀況下,生產num歌產品 for(int i=1;i<=num;++i){ list.add(new Object()); } System.out.println("已經生產產品數:"+num+"/t 現倉儲量爲:"+list.size()); list.notifyAll(); } } /** * * 消費num個產品 */ public void consume(int num){ //獲取鎖 synchronized(list){ //緩存區剩餘容量不足 while(list.size() < num){ System.out.println("要消費的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行消費任務!"); try{ //因爲條件不知足,消費阻塞 list.wait() }catch(InterruptedException e){ e.printStackTrace(); } } //在生產條件知足狀況下,生產num歌產品 for(int i=1;i<=num;++i){ list.remove(); } System.out.println("已經消費產品數:"+num+"/t 現倉儲量爲:"+list.size()); list.notifyAll(); } } //list getter//setter //MAX_SIZE getter }
public class Producer extends Thread{ //每次生產的產品數量 private int num; //倉庫對象 private Storage storage; //構造函數,設置倉庫 public Producer(Storage storage){ this.storage = storage; } //線程run函數 public void run(){ produce(); } //調用倉庫的生產方法 public void produce(){ storage.produce(); } //num storage的getter(),setter()方法 }
/** * * 消費者線程類 */ public class Consumer extends Thread{ private int num; private Storage storage; public void Consumer(Storage storage){ this.storage = storage; } public void run(){ consume(); } public void consume(){ storage.consume(); } //num和storage的getter(),setter()方法 }
public class Test{ public static void main(String args[]){ //倉庫對象 Storage storage = new Storage(); //生產者對象 Producer p1 = new Producer(); Producer p2 = new Producer(); Producer p3 = new Producer(); Producer p4 = new Producer(); Producer p5 = new Producer(); Producer p6 = new Producer(); //消費者對象 Consumer c1 = new Consumer(); Consumer c2 = new Consumer(); Consumer c3 = new Consumer(); Consumer c4 = new Consumer(); Consumer c5 = new Consumer(); //設置生產者生產數量 p1.setNum(10); p2.setNum(10); p3.setNum(10); p4.setNum(40); p5.setNum(50); p6.setNum(30); //設置消費者消費數量 c1.setNum(10); c2.setNum(20); c3.setNum(10); c4.setNum(30); c5.setNum(10); //執行線程 p1.start(); p2.start(); p3.start(); p4.start(); p5.start(); p6.start(); c1.start(); c2.start(); c3.start(); c4.start(); c5.start(); } }
2).await()和signal()方式實現spa
public class Storage{ //緩衝區最大承載量 private final int MAX_SIZE = 100; //緩衝區存儲的載體 private LinkedList<Object> list = new LinkedList<Object>(); //鎖 private final Lock lock = new ReentrantLock(); //倉庫滿的條件變量 private final Condition full = lock.newCondition(); //倉庫空的條件變量 private final Condition empty = lock.newCondition(); /** * * 生產num個產品 */ public void produce(int num){ //獲取鎖 lock.lock(); //緩存區剩餘容量不足 while(list.size() + num > MAX_SIZE){ System.out.println("要生產的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行生產任務!"); try{ //因爲條件不知足,生產阻塞 full.await() }catch(InterruptedException e){ e.printStackTrace(); } } //在生產條件知足狀況下,生產num歌產品 for(int i=1;i<=num;++i){ list.add(new Object()); } System.out.println("已經生產產品數:"+num+"/t 現倉儲量爲:"+list.size()); //喚醒其它全部線程 full.signalAll(); empty.signalAll(); //釋放鎖 lock.unlock(); } /** * * 消費num個產品 */ public void consume(int num){ //獲取鎖 lock.lock(); //緩存區剩餘容量不足 while(list.size() < num){ System.out.println("要消費的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行消費任務!"); try{ //因爲條件不知足,消費阻塞 empty.await() }catch(InterruptedException e){ e.printStackTrace(); } } //在生產條件知足狀況下,生產num歌產品 for(int i=1;i<=num;++i){ list.remove(); } System.out.println("已經消費產品數:"+num+"/t 現倉儲量爲:"+list.size()); full.signalAll(); empty.signalAll(); //釋放鎖 lock.unlock(); } //list getter//setter //MAX_SIZE getter }
3).BlockingQueue阻塞隊列來實現線程
public class Storage{ //緩衝區最大承載量 private final int MAX_SIZE = 100; //緩衝區存儲的載體 private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>(100); /** * * 生產num個產品 */ public void produce(int num){ //緩存區剩餘容量不足 while(list.size() == MAX_SIZE){ System.out.println(「庫存量:"+MAX_SIZE+"/t 暫時不能執行生產任務!"); } //在生產條件知足狀況下,生產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){ //緩存區剩餘容量不足 while(list.size() == 0){ System.out.println("庫存量:"+0+"/t 暫時不能執行消費任務!"); } //在生產條件知足狀況下,生產num歌產品 for(int i=1;i<=num;++i){ try{ list.take();//容量爲0時,自動阻塞 }catch(InterruptedException e){ e.printStackTrace(); } } System.out.println("現倉儲量爲:"+list.size()); } //list getter//setter //MAX_SIZE getter }