=========================使用synchronized,配合Object的wait()/notify()實現生產者消費者======================
思考問題:
1.為什么用wait()+notify()實現生產者消費者模式?
wait()方法可以暫停線程,並釋放對象鎖
notify()方法可以喚醒需要該對象鎖的其他線程,並在執行完后續步驟,到了synchronized臨界區后,才會把鎖釋放
2.為什么wait()、notify()、notifyAll()方法需要放在同步代碼塊中執行?
wait()方法暫停線程執行,並立即釋放對象鎖 notify()/notifyAll() 方法喚醒其他等待該對象鎖的線程,並在執行完同步代碼塊中的后續步驟后,釋放對象鎖 notify()和notifyAll()的區別在於: notify只會喚醒其中一個線程, notifyAll則會喚醒全部線程。 至於notify會喚醒哪個線程,是由線程調度器決定的。
因為這三個方法都需要獲取到對象鎖才能有效執行。否則就會拋異常:java.lang.IllegalMonitorStateException
3.wait()是暫停的哪個線程?notify()喚醒的是哪個線程?
wait()是暫停當前線程。
notify()則是喚醒等待當前對象鎖的線程
4.什么是生產者消費者模式
一個產數據,一個用數據,中間最多再加上個存取倉庫
生產者消費者模式 就是java多線程通信一個很好的例子
5.生產着消費者模式特點是什么
1.解耦,生產者干生產者的事情,消費者干消費者的事情
2.支持高並發,可以同時多個生成,多個消費,互不影響
6.一對一的生產者消費者模式:
1>早餐類:

package com.sxd.swapping.test.ProducerAndConsumerTest; /** * 早餐基礎類 * * wait() * notify() * notifyAll() * 三個方法 需要放在同步代碼塊中執行 因為要獲取對象鎖 */ public class Breakfast{ private String food; private String drink; private boolean flag = false;//flag = false 表示需要生產 flag = true 表示需要消費 public synchronized void makeBreakfast(String food,String drink){ System.out.println("生產者進入--->標志值為:"+flag); if (flag){ try { System.out.println("make---wait()暫停,釋放對象鎖"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.food = food; try { System.out.println("make---sleep()休眠,不釋放對象鎖"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.drink = drink; System.out.println("make---生產者制造東西完成----"); this.flag = true; System.out.println("make---notify()喚醒,標志值為"+flag); notify(); } public synchronized void eatBreakfast(){ System.out.println("消費者進入--->標志值為:"+flag); if(!flag){ try { System.out.println("eat---wait()"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { System.out.println("eat---sleep()"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("吃東西---"+this.food+";喝東西---"+this.drink); this.flag = false; System.out.println("eat---notify()喚醒,標志值為"+flag); notify(); } }
2> 生產者類:

package com.sxd.swapping.test.ProducerAndConsumerTest; public class Producer implements Runnable{ private Breakfast breakfast; public Producer(Breakfast breakfast) { this.breakfast = breakfast; } @Override public void run() { int i = 7; for (int i1 = 0; i1 < i; i1++) { if (i1 %2 == 0){ this.breakfast.makeBreakfast("饅頭","豆漿"); }else { this.breakfast.makeBreakfast("面包","冷飲"); } } } }
3>消費者類:

package com.sxd.swapping.test.ProducerAndConsumerTest; public class Consumer implements Runnable{ private Breakfast breakfast; public Consumer(Breakfast breakfast) { this.breakfast = breakfast; } @Override public void run() { int i = 7; for (int i1 = 0; i1 < i; i1++) { System.out.println("星期"+(i1+1)+"---消費者要來吃東西了"); this.breakfast.eatBreakfast(); } } }
4>線程啟動主測試類:

package com.sxd.swapping.test.ProducerAndConsumerTest; public class Test { public static void main(String[] args) { Breakfast breakfast = new Breakfast(); new Thread(new Producer(breakfast)).start(); new Thread(new Consumer(breakfast)).start(); } }
5>展示結果:
===========================使用Lock,配合Condition的await()/signal()實現生產者消費者============================
1.早飯類,提供生產方法和消費方法

package com.sxd.swapping.test.ProducerAndConsumerTest; import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * Lock配合condition實現生產者消費者模式 * * @author sxd * @date 2019/8/6 9:08 */ public class Condition_Breakfast { private LinkedList<String> breakfastList;//早飯資源容器 private int maxSize;//最大量早飯資源數量 自定義 private Lock lock; //鎖 private Condition comsumerCondition;//滿條件【即代表消費者等待隊列】 private Condition producerCondition;//不滿條件【即代表生產者等待隊列】 //自定義 最大共享資源數量 public Condition_Breakfast(int maxSize) { this.maxSize = maxSize; breakfastList = new LinkedList<>(); lock = new ReentrantLock(); comsumerCondition = lock.newCondition(); producerCondition = lock.newCondition(); } public void produce(String str){ lock.lock(); try { while (maxSize == breakfastList.size()){ System.out.println("如果早餐共享資源已經滿足最大量,則進入本方法的當前線程們,進入notFullCondition的等待隊列中,線程掛起"); producerCondition.await(); } breakfastList.add(str); System.out.println("生產早飯:"+str); System.out.println("早飯已經被生產了,喚醒消費者等待隊列中的線程,可以繼續開始消費了"); comsumerCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public String consume(){ String str = null; lock.lock(); try { while (breakfastList.size() == 0 ){ System.out.println("如果早飯共享資源完全==0,就將消費者們掛起,等待生產者生產后再去喚醒消費者們"); comsumerCondition.await(); } str = breakfastList.poll(); System.out.println("消費早飯:"+str); System.out.println("早飯已經被消費了,喚醒生產者等待隊列中的 線程,可以繼續生產了"); producerCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } return str; } }
2.早飯類的生產者

package com.sxd.swapping.test.ProducerAndConsumerTest; /** * @author sxd * @date 2019/8/6 9:26 */ public class Condition_Producer implements Runnable { Condition_Breakfast breakfast; public Condition_Producer(Condition_Breakfast breakfast) { this.breakfast = breakfast; } @Override public void run() { int i = 7; String threadName = Thread.currentThread().getName(); for (int i1 = 0; i1 < i; i1++) { if (i1 %2 == 0){ this.breakfast.produce(threadName+"大饅頭"+i1); }else { this.breakfast.produce(threadName+"大包子"+i1); } } } }
3.早飯類的消費者

package com.sxd.swapping.test.ProducerAndConsumerTest; /** * @author sxd * @date 2019/8/6 9:28 */ public class Condition_Comsumer implements Runnable{ Condition_Breakfast breakfast; public Condition_Comsumer(Condition_Breakfast breakfast) { this.breakfast = breakfast; } @Override public void run() { int i = 7; for (int i1 = 0; i1 < i; i1++) { this.breakfast.consume(); } } }
4.測試類

package com.sxd.swapping.test.ProducerAndConsumerTest; /** * @author sxd * @date 2019/8/6 9:30 */ public class Test2 { public static void main(String[] args) { Condition_Breakfast breakfast = new Condition_Breakfast(16); new Thread(new Condition_Producer(breakfast)).start(); new Thread(new Condition_Producer(breakfast)).start(); new Thread(new Condition_Producer(breakfast)).start(); new Thread(new Condition_Comsumer(breakfast)).start(); new Thread(new Condition_Comsumer(breakfast)).start(); new Thread(new Condition_Comsumer(breakfast)).start(); } }
5.啟動效果