程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java線程:並發協作-生產者消費者模型

Java線程:並發協作-生產者消費者模型

編輯:關於JAVA

實際上,准確說應該是“生產者-消費者-倉儲”模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。

對於此模型,應該明確一下幾點:

1、生產者僅僅在倉儲未滿時候生產,倉滿則停止生產。

2、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。

3、當消費者發現倉儲沒產品可消費時候會通知生產者生產。

4、生產者在生產出可消費產品時候,應該通知等待的消費者去消費。

此模型將要結合java.lang.Object的wait與notify、notifyAll方法來實現以上的需求。這是非常重要的。

/**
* Java線程:並發協作-生產者消費者模型
*
* @author leizhimin
*/
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;
         }
         /**
          * 生產指定數量的產品
          *
          * @param neednum
          */
         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();
         }
         /**
          * 消費指定數量的產品
          *
          * @param neednum
          */
         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() 方法,起到的是一個通知作用,不釋放鎖,也不獲取鎖。只是告訴該對象上等待的線程“可以競爭執行了,都醒來去執行吧”。

本例僅僅是生產者消費者模型中最簡單的一種表示,本例中,如果消費者消費的倉儲量達不到滿足,而又沒有生產者,則程序會一直處於等待狀態,這當然是不對的。實際上可以將此例進行修改,修改為,根據消費驅動生產,同時生產兼顧倉庫,如果倉不滿就生產,並對每次最大消費量做個限制,這樣就不存在此問題了,當然這樣的例子更復雜,更難以說明這樣一個簡單模型。

我喜歡簡單的例子。

此出處:http://lavasoft.blog.51cto.com/62575/221932

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved