Java線程十四:併發協做-生產者消費者模型

Java線程:併發協做-生產者消費者模型
 
對於多線程程序來講,無論任何編程語言,生產者和消費者模型都是最經典的。就像學習每一門編程語言同樣,Hello World!都是最經典的例子。
 
實際上,準確說應該是「生產者-消費者-倉儲」模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。
對於此模型,應該明確一下幾點:
一、生產者僅僅在倉儲未滿時候生產,倉滿則中止生產。
二、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。
三、當消費者發現倉儲沒產品可消費時候會通知生產者生產。
四、生產者在生產出可消費產品時候,應該通知等待的消費者去消費。
 
此模型將要結合java.lang.Object的wait與notify、notifyAll方法來實現以上的需求。這是很是重要的。
 
 
public  class  Test { 
                public  static  void  main(String[] args) { 
                                Godown godown =  new  Godown(30); 
                                Consumer c1 =  new  Consumer(50, godown); 
                                Consumer c2 =  new  Consumer(20, godown); 
                                Consumer c3 =  new  Consumer(30, godown); 
                                Producer p1 =  new  Producer(10, godown); 
                                Producer p2 =  new  Producer(10, godown); 
                                Producer p3 =  new  Producer(10, godown); 
                                Producer p4 =  new  Producer(10, godown); 
                                Producer p5 =  new  Producer(10, godown); 
                                Producer p6 =  new  Producer(10, godown); 
                                Producer p7 =  new  Producer(80, godown); 

                                c1.start(); 
                                c2.start(); 
                                c3.start(); 
                                p1.start(); 
                                p2.start(); 
                                p3.start(); 
                                p4.start(); 
                                p5.start(); 
                                p6.start(); 
                                p7.start(); 
               


 
class  Godown { 
                public  static  final  int  max_size = 100;  //最大庫存量 
                public  int  curnum;          //當前庫存量 

                Godown() { 
               

                Godown( int  curnum) { 
                                this.curnum = curnum; 
               

                 
                public  synchronized  void  produce( int  neednum) { 
                                //測試是否須要生產 
                                while  (neednum + curnum > max_size) { 
                                                System.out.println( "要生產的產品數量"  + neednum +  "超過剩餘庫存量"  + (max_size - curnum) +  ",暫時不能執行生產任務!"); 
                                                try 
                                                                //當前的生產線程等待 
                                                                wait(); 
                                                catch  (InterruptedException e) { 
                                                                e.printStackTrace(); 
                                               
                               
                                //知足生產條件,則進行生產,這裏簡單的更改當前庫存量 
                                curnum += neednum; 
                                System.out.println( "已經生產了"  + neednum +  "個產品,現倉儲量爲"  + curnum); 
                                //喚醒在此對象監視器上等待的全部線程 
                                notifyAll(); 
               

                 
                public  synchronized  void  consume( int  neednum) { 
                                //測試是否可消費 
                                while  (curnum < neednum) { 
                                                try 
                                                                //當前的生產線程等待 
                                                                wait(); 
                                                catch  (InterruptedException e) { 
                                                                e.printStackTrace(); 
                                               
                               
                                //知足消費條件,則進行消費,這裏簡單的更改當前庫存量 
                                curnum -= neednum; 
                                System.out.println( "已經消費了"  + neednum +  "個產品,現倉儲量爲"  + curnum); 
                                //喚醒在此對象監視器上等待的全部線程 
                                notifyAll(); 
               


 
class  Producer  extends  Thread { 
                private  int  neednum;                                //生產產品的數量 
                private  Godown godown;                        //倉庫 

                Producer( int  neednum, Godown godown) { 
                                this.neednum = neednum; 
                                this.godown = godown; 
               

                public  void  run() { 
                                //生產指定數量的產品 
                                godown.produce(neednum); 
               


 
class  Consumer  extends  Thread { 
                private  int  neednum;                                //生產產品的數量 
                private  Godown godown;                        //倉庫 

                Consumer( int  neednum, Godown godown) { 
                                this.neednum = neednum; 
                                this.godown = godown; 
               

                public  void  run() { 
                                //消費指定數量的產品 
                                godown.consume(neednum); 
               
}
 
已經生產了10個產品,現倉儲量爲40 
已經生產了10個產品,現倉儲量爲50 
已經消費了50個產品,現倉儲量爲0 
已經生產了80個產品,現倉儲量爲80 
已經消費了30個產品,現倉儲量爲50 
已經生產了10個產品,現倉儲量爲60 
已經消費了20個產品,現倉儲量爲40 
已經生產了10個產品,現倉儲量爲50 
已經生產了10個產品,現倉儲量爲60 
已經生產了10個產品,現倉儲量爲70 

Process finished with exit code 0 
 
說明:
對於本例,要說明的是當發現不能知足生產或者消費條件的時候,調用對象的wait方法,wait方法的做用是釋放當前線程的所得到的鎖,並調用對象的notifyAll() 方法,通知(喚醒)該對象上其餘等待線程,使得其繼續執行。這樣,整個生產者、消費者線程得以正確的協做執行。
notifyAll() 方法,起到的是一個通知做用,不釋放鎖,也不獲取鎖。只是告訴該對象上等待的線程「能夠競爭執行了,都醒來去執行吧」。
 
本例僅僅是生產者消費者模型中最簡單的一種表示,本例中,若是消費者消費的倉儲量達不到知足,而又沒有生產者,則程序會一直處於等待狀態,這固然是不對的。實際上能夠將此例進行修改,修改成,根據消費驅動生產,同時生產兼顧倉庫,若是倉不滿就生產,並對每次最大消費量作個限制,這樣就不存在此問題了,固然這樣的例子更復雜,更難以說明這樣一個簡單模型。
相關文章
相關標籤/搜索