Java多線程之消費者生產者模式
作者:shijinupc
這個實例應該是學習線程的一個經典例子,生產者和消費者模式。代碼寫的很好,詳細請看內容。
- /*@author shijin
- * 生產者與消費者模型中,要保證以下幾點:
- * 1 同一時間內只能有一個生產者生產 生產方法加鎖sychronized
- * 2 同一時間內只能有一個消費者消費 消費方法加鎖sychronized
- * 3 生產者生產的同時消費者不能消費 生產方法加鎖sychronized
- * 4 消費者消費的同時生產者不能生產 消費方法加鎖sychronized
- * 5 共享空間空時消費者不能繼續消費 消費前循環判斷是否為空,空的話將該線程wait,釋放鎖允許其他同步方法執行
- * 6 共享空間滿時生產者不能繼續生產 生產前循環判斷是否為滿,滿的話將該線程wait,釋放鎖允許其他同步方法執行
- */
- //主類
- class ProducerConsumer
- {
- public static void main(String[] args)
- {
- StackBasket s = new StackBasket();
- Producer p = new Producer(s);
- Consumer c = new Consumer(s);
- Thread tp = new Thread(p);
- Thread tc = new Thread(c);
- tp.start();
- tc.start();
- }
- }
- //
- class Mantou
- {
- private int id;
- Mantou(int id){
- this.id = id;
- }
- public String toString(){
- return "Mantou :" + id;
- }
- }
- //共享棧空間
- class StackBasket
- {
- Mantou sm[] = new Mantou[6];
- int index = 0;
- /**
- * show 生產方法.
- * show 該方法為同步方法,持有方法鎖;
- * show 首先循環判斷滿否,滿的話使該線程等待,釋放同步方法鎖,允許消費;
- * show 當不滿時首先喚醒正在等待的消費方法,但是也只能讓其進入就緒狀態,
- * show 等生產結束釋放同步方法鎖后消費才能持有該鎖進行消費
- * @param m 元素
- * @return 沒有返回值
- */
- public synchronized void push(Mantou m){
- try{
- while(index == sm.length){
- System.out.println("!!!!!!!!!生產滿了!!!!!!!!!");
- this.wait();
- }
- this.notify();
- }catch(InterruptedException e){
- e.printStackTrace();
- }catch(IllegalMonitorStateException e){
- e.printStackTrace();
- }
- sm[index] = m;
- index++;
- System.out.println("生產了:" + m + " 共" + index + "個饅頭");
- }
- /**
- * show 消費方法
- * show 該方法為同步方法,持有方法鎖
- * show 首先循環判斷空否,空的話使該線程等待,釋放同步方法鎖,允許生產;
- * show 當不空時首先喚醒正在等待的生產方法,但是也只能讓其進入就緒狀態
- * show 等消費結束釋放同步方法鎖后生產才能持有該鎖進行生產
- * @param b true 表示顯示,false 表示隱藏
- * @return 沒有返回值
- */
- public synchronized Mantou pop(){
- try{
- while(index == 0){
- System.out.println("!!!!!!!!!消費光了!!!!!!!!!");
- this.wait();
- }
- this.notify();
- }catch(InterruptedException e){
- e.printStackTrace();
- }catch(IllegalMonitorStateException e){
- e.printStackTrace();
- }
- index--;
- System.out.println("消費了:---------" + sm[index] + " 共" + index + "個饅頭");
- return sm[index];
- }
- }
- class Producer implements Runnable
- {
- StackBasket ss = new StackBasket();
- Producer(StackBasket ss){
- this.ss = ss;
- }
- /**
- * show 生產進程.
- */
- public void run(){
- for(int i = 0;i < 20;i++){
- Mantou m = new Mantou(i);
- ss.push(m);
- // System.out.println("生產了:" + m + " 共" + ss.index + "個饅頭");
- // 在上面一行進行測試是不妥的,對index的訪問應該在原子操作里,因為可能在push之后此輸出之前又消費了,會產生輸出混亂
- try{
- Thread.sleep((int)(Math.random()*500));
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- }
- class Consumer implements Runnable
- {
- StackBasket ss = new StackBasket();
- Consumer(StackBasket ss){
- this.ss = ss;
- }
- /**
- * show 消費進程.
- */
- public void run(){
- for(int i = 0;i < 20;i++){
- Mantou m = ss.pop();
- // System.out.println("消費了:---------" + m + " 共" + ss.index + "個饅頭");
- // 同上 在上面一行進行測試也是不妥的,對index的訪問應該在原子操作里,因為可能在pop之后此輸出之前又生產了,會產生輸出混亂
- try{
- Thread.sleep((int)(Math.random()*1000));
- }catch(InterruptedException e){
- e.printStackTrace();
- }
- }
- }
- }
原文鏈接:http://blog.csdn.net/shijinupc/article/details/7250407
【編輯推薦】
責任編輯:林師授
來源:
shijinupc的博客