1. 程式人生 > >多線程學習-基礎(十二)生產者消費者模型:wait(),sleep(),notify()實現

多線程學習-基礎(十二)生產者消費者模型:wait(),sleep(),notify()實現

都是 exce 生產 runnable 下午 util 庫存 jason 最大

一、多線程模型一:生產者消費者模型

(1)模型圖:(從網上找的圖,清晰明了)

技術分享圖片

(2)生產者消費者模型原理說明:

  這個模型核心是圍繞著一個“倉庫”的概念,生產者消費者都是圍繞著:“倉庫”來進行操作,一個倉庫同時只能被一個生產者線程或一個消費者線程所操作,synchronized鎖住的也是這個倉庫,倉庫是一個容器,所以會有邊界值,0和倉庫可存放上限,在這個上限內,可以設置多種級別,不同的級別可以執行不同的策略流程。

(3)本案例使用知識點:

  Thread.currentThread().interrupt();//中斷線程

  this.notify();//喚醒其他線程

  this.wait();//停止出貨

  Thread.sleep(1000);//放置一個線程占用cpu過久

這些知識點都是多線程的基礎知識點,以後會嘗試使用:BlockingQueue,線程池來擴展這些簡單的案例,個人覺得,先掌握好簡單的使用,然後再在其上擴展,記憶會比較深刻一點。

二、案例源碼

  案例說明:

     本案例有:產品類Product ,倉庫類Warehouse , 生產者線程(實現Runnable)Producer , 消費者線程(實現Runnable)Consumer ,以及一個啟動類ThreadStart

 好了,直接貼出代碼吧。

產品類Product

 1 package
com.jason.proCusModels; 2 /** 3 * 產品類 4 * @function 5 * @author 小風微涼 6 * @time 2018-4-26 下午8:00:40 7 */ 8 public class Product { 9 //產品名稱 10 private String pName; 11 //產品編號 12 private String proNo; 13 public Product(String pName,String proNo){ 14 this.pName=pName; 15
this.proNo=proNo; 16 } 17 //設置getter方法 18 public String getpName() { 19 return pName; 20 } 21 public String getProNo() { 22 return proNo; 23 } 24 //重寫toString方法 25 @Override 26 public String toString() { 27 return "產品名稱:"+this.pName+",產品編號:"+this.proNo; 28 } 29 }

倉庫類Warehouse

 1 package com.jason.proCusModels;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 /**
 5  * 倉庫類
 6  * @function  
 7  * @author 小風微涼
 8  * @time  2018-4-26 下午7:59:34
 9  */
10 public class Warehouse {
11     //倉庫名稱
12     private String name;
13     //倉庫最大容量上限
14     private int MAX_COUNT=100;
15     //設置倉庫貨物預警下限:此處可以加設進貨策略,不同的缺貨程度,設置不同的進貨速度(以後再補充)
16     private int MIN_COUNT=20;
17     //倉庫存放商品的容器
18     public static  List<Product> proList;
19     //靜態塊
20     static{
21         proList=new ArrayList<Product>();
22     }
23     //構造器
24     public Warehouse(String name){
25         this.name=name;
26     }
27     /**
28      * 倉庫進貨
29      * @param count 進貨數量
30      */
31     public synchronized void Purchase(int count){        
32         //判斷當前貨物+count是否超過上限     如果超過,則停止進貨   只允許出貨
33         int currCount=proList.size();
34         if(currCount+count>MAX_COUNT){
35             this.notify();//喚醒其他線程
36             try {
37                 System.out.println(Thread.currentThread().getName()+"準備進貨:"+count+"個產品,當前倉庫貨物有:"+currCount+"個,【貨物超過倉庫存放上限:"+MAX_COUNT+"】,已經停止進貨");
38                 this.wait();//停止進貨
39             } catch (InterruptedException e) {
40                 e.printStackTrace();
41                 Thread.currentThread().interrupt();//中斷線程
42             }
43         }else{//判斷:當前貨物+count沒有超過上限   則可以繼續進貨
44             if(currCount<=MIN_COUNT){
45                 System.out.println("當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!");
46             }
47             //開始進貨
48             for(int i=0;i<count;i++){
49                 //拿到產品
50                 Product prod=new Product("IphoneX", "*");//編號隨意,暫時不會用到
51                 //入庫
52                 proList.add(prod);                
53             }
54             System.out.println(Thread.currentThread().getName()+"準備進貨:"+count+"個產品,當前倉庫貨物有:"+currCount+"個,進貨後倉庫總有:"+proList.size());
55         }
56         try {
57             Thread.sleep(1000);//放置一個線程占用cpu過久
58         } catch (InterruptedException e) {
59             e.printStackTrace();
60         }
61     } 
62     /**
63      * 倉庫出貨
64      * @param count·出貨數量
65      */
66     public  synchronized void Shipments(int count){
67         //如果當前倉庫貨物余貨為0  或者出貨數量<count  則停止出貨   開始進貨
68         int currCount=proList.size();
69         if(currCount==0 || currCount<count){
70             this.notify();//喚醒其他線程
71             try {
72                 System.out.println(Thread.currentThread().getName()+"準備出貨:"+count+"個產品,當前倉庫貨物有:"+currCount+"個,【貨物短缺,請盡快進貨】,已經停止出貨");
73                 this.wait();//停止出貨
74             } catch (InterruptedException e) {
75                 e.printStackTrace();
76                 Thread.currentThread().interrupt();//中斷線程
77             }
78         }else{//倉庫貨物充足,可繼續出貨
79             //出貨
80             proList=proList.subList(count, proList.size());
81             System.out.println(Thread.currentThread().getName()+"準備出貨:"+count+"個產品,當前倉庫貨物有:"+currCount+"個,出貨後倉庫總有:"+proList.size());
82         }
83         try {
84             Thread.sleep(1000);//放置一個線程占用cpu過久
85         } catch (InterruptedException e) {
86             e.printStackTrace();
87         }
88     }
89     /**
90      * 拿到倉庫容器
91      * @return
92      */
93     public static List<Product> getProList() {
94         return proList;
95     }
96 }

生產者線程(實現Runnable)Producer

 1 package com.jason.proCusModels;
 2 /**
 3  * 生產者類(線程)
 4  * @function  
 5  * @author 小風微涼
 6  * @time  2018-4-26 下午7:57:47
 7  */
 8 public class Producer implements Runnable{
 9     //生產者名稱
10     private String name;
11     //倉庫對象
12     private Warehouse whose;//這樣寫只是為了讓關系更加清晰   實際倉庫容器:Warehouse.proList    
13     //消費產品數量
14     private int threadCount;
15     //構造器
16     public Producer(String name,int threadCount,Warehouse whose){
17         this.name=name;
18         this.whose=whose;
19         this.threadCount=threadCount;
20     }
21     public void run() {
22         Thread.currentThread().setName(this.name);
23         //開始進貨
24         while(true){
25             whose.Purchase(threadCount);
26         }        
27     }
28 }

消費者線程(實現Runnable)Consumer

 1 package com.jason.proCusModels;
 2 /**
 3  * 消費者類(線程)
 4  * @function  
 5  * @author 小風微涼
 6  * @time  2018-4-26 下午7:58:59
 7  */
 8 public class Consumer  implements Runnable{
 9     //消費者名稱
10     private String name;
11     //倉庫對象
12     private Warehouse whose;//這樣寫只是為了讓關系更加清晰   實際倉庫容器:Warehouse.proList    
13     //消費產品數量
14     private int threadCount;
15     //構造器
16     public Consumer(String name,int threadCount,Warehouse whose){
17         this.name=name;
18         this.whose=whose;
19         this.threadCount=threadCount;
20     }
21     public void run() {
22         Thread.currentThread().setName(this.name);
23         //開始出貨
24         while(true){
25             whose.Shipments(threadCount);
26         }
27     }
28 }

一個啟動類ThreadStart

 1 package com.jason.proCusModels;
 2 /**
 3  * 多線程學習
 4  * @function  生產者消費者模型啟動類
 5  * @author 小風微涼
 6  * @time  2018-4-26 下午8:51:56
 7  */
 8 public class ThreadStart {
 9     /**
10      * 啟動項
11      * @param args
12      */
13     public static void main(String[] args) {
14         //創建一個倉庫
15         Warehouse whose=new Warehouse("1號倉庫");
16         //創建10個生產者線程
17         for(int i=1;i<=10;i++){
18             new Thread(new Producer(i+"號生產者",(int)(Math.random()*10+1),whose)).start();
19         }
20         //創建15個消費者線程
21         for(int i=1;i<=15;i++){
22             new Thread(new Consumer(i+"號消費者",(int)(Math.random()*10+1),whose)).start();
23         }
24     }
25 }

運行結果:(僅截取部分結果)

當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
1號生產者準備進貨:6個產品,當前倉庫貨物有:0個,進貨後倉庫總有:6
12號消費者準備出貨:1個產品,當前倉庫貨物有:6個,出貨後倉庫總有:5
15號消費者準備出貨:3個產品,當前倉庫貨物有:5個,出貨後倉庫總有:2
14號消費者準備出貨:3個產品,當前倉庫貨物有:2個,【貨物短缺,請盡快進貨】,已經停止出貨
11號消費者準備出貨:9個產品,當前倉庫貨物有:2個,【貨物短缺,請盡快進貨】,已經停止出貨
13號消費者準備出貨:2個產品,當前倉庫貨物有:2個,出貨後倉庫總有:0
10號消費者準備出貨:6個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
4號消費者準備出貨:1個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
6號消費者準備出貨:2個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
9號消費者準備出貨:2個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
8號消費者準備出貨:9個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
5號消費者準備出貨:5個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
7號消費者準備出貨:5個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
3號消費者準備出貨:4個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
2號消費者準備出貨:3個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
1號消費者準備出貨:5個產品,當前倉庫貨物有:0個,【貨物短缺,請盡快進貨】,已經停止出貨
當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
10號生產者準備進貨:1個產品,當前倉庫貨物有:0個,進貨後倉庫總有:1
當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
9號生產者準備進貨:3個產品,當前倉庫貨物有:1個,進貨後倉庫總有:4
當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
8號生產者準備進貨:5個產品,當前倉庫貨物有:4個,進貨後倉庫總有:9
當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
8號生產者準備進貨:5個產品,當前倉庫貨物有:9個,進貨後倉庫總有:14
當前倉庫剩余貨物數量,在最低警戒線一下,請抓緊時間補貨!!!!!!!
7號生產者準備進貨:9個產品,當前倉庫貨物有:14個,進貨後倉庫總有:23
6號生產者準備進貨:9個產品,當前倉庫貨物有:23個,進貨後倉庫總有:32
5號生產者準備進貨:1個產品,當前倉庫貨物有:32個,進貨後倉庫總有:33
4號生產者準備進貨:8個產品,當前倉庫貨物有:33個,進貨後倉庫總有:41
3號生產者準備進貨:9個產品,當前倉庫貨物有:41個,進貨後倉庫總有:50
2號生產者準備進貨:8個產品,當前倉庫貨物有:50個,進貨後倉庫總有:58
3號生產者準備進貨:9個產品,當前倉庫貨物有:58個,進貨後倉庫總有:67
4號生產者準備進貨:8個產品,當前倉庫貨物有:67個,進貨後倉庫總有:75
5號生產者準備進貨:1個產品,當前倉庫貨物有:75個,進貨後倉庫總有:76
6號生產者準備進貨:9個產品,當前倉庫貨物有:76個,進貨後倉庫總有:85
6號生產者準備進貨:9個產品,當前倉庫貨物有:85個,進貨後倉庫總有:94
6號生產者準備進貨:9個產品,當前倉庫貨物有:94個,【貨物超過倉庫存放上限:100】,已經停止進貨
7號生產者準備進貨:9個產品,當前倉庫貨物有:94個,【貨物超過倉庫存放上限:100】,已經停止進貨
8號生產者準備進貨:5個產品,當前倉庫貨物有:94個,進貨後倉庫總有:99
9號生產者準備進貨:3個產品,當前倉庫貨物有:99個,【貨物超過倉庫存放上限:100】,已經停止進貨
10號生產者準備進貨:1個產品,當前倉庫貨物有:99個,進貨後倉庫總有:100
2號消費者準備出貨:3個產品,當前倉庫貨物有:100個,出貨後倉庫總有:97
2號消費者準備出貨:3個產品,當前倉庫貨物有:97個,出貨後倉庫總有:94
3號消費者準備出貨:4個產品,當前倉庫貨物有:94個,出貨後倉庫總有:90
3號消費者準備出貨:4個產品,當前倉庫貨物有:90個,出貨後倉庫總有:86
3號消費者準備出貨:4個產品,當前倉庫貨物有:86個,出貨後倉庫總有:82
3號消費者準備出貨:4個產品,當前倉庫貨物有:82個,出貨後倉庫總有:78
5號消費者準備出貨:5個產品,當前倉庫貨物有:78個,出貨後倉庫總有:73

說明:這個用不著分析了,過程和結果很明顯,思路還處於初級階段,以後會慢慢改進優化。如果您有好的建議,歡迎指正,交流促進進步!

多線程學習-基礎(十二)生產者消費者模型:wait(),sleep(),notify()實現