生產者模式實現總結

前言

消費者生產者模式是java中多線程的典型模式,它牽涉到java中多個線程交互的一些方式。下面根據一些典型的實現來說明;

一、方式1

該方式源碼出處爲:http://eric-619.iteye.com/blog/693681

生產者-消費者模型準確說應該是“生產者-消費者-倉儲”模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。
對於此模型,應該明確一下幾點:
1、生產者僅僅在倉儲未滿時候生產,倉滿則停止生產。
2、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。
3、當消費者發現倉儲沒產品可消費時候會通知生產者生產。
4、生產者在生產出可消費產品時候,應該通知等待的消費者去消費
此模型將要結合java.lang.Object的wait與notify、notifyAll方法來實現以上的需求。這是非常重要的。

生產者和消費者通過共享內存的方式進行通信;它們共享的內存是:SyncStack對象;生產者通過SyncStack的同步方法pop向其中添加對象;消費者通過SyncStack的同步方法pop方法在SyncStack對象中獲取對象;這是對象間共享內存(或共享數據區域)的方式進行的通信。

關鍵點詳解:

其中的關鍵是共享內存區域中的兩個同步方法,及同步方法中wait()方法的調用;同步保證了對象只能被一個線程佔用,wait保證了當線程在等待的過程中釋放自己的鎖,使得其它對象有機會獲得對象的鎖;

缺點:

在多個線程進行操作時(有較多生產者和消費者時),使用notifyAll方法會造成不必要進行喚醒的方法進行線程的調度,從而導致不必要的時間花銷;

比如一個消費者線程調用了notifyAll(),則會喚醒其它消費者,但是其本意是喚醒生產者來製造物品;由此可見,該方法並沒有進行定點的通知。

複製代碼
    /*
    * 生產者消費者問題其含義就是先生產出了產品,才能拉出去讓消費者購買 
    *    1、多個線程數據共享區域化思想!
    *    2、生產者消費者 
    *     
    * 二、synchronized加鎖: 
    *  
    */  
      
      
    public class ProCon{ //主方法  
      
    public static void main(String[] args){  
    SyncStack stack = new SyncStack();  
    Consumer p = new Consumer(stack);  
    Producer c = new Producer(stack);  
      
      
    new Thread(p).start();  
    new Thread(c).start();  
    }  
    }  
      
    class Producer implements Runnable{   //生產者  
        private SyncStack stack;  
      
        public Producer(SyncStack stack){  
        this.stack = stack;  
         }  
      
        public void run(){  
        for (int i = 0; i < stack.pro().length; i++){  
        String product = "產品"+i;  
        stack.push(product);  
        System.out.println("生產了: "+product);  
        try{  
         Thread.sleep(200);  
         }catch(InterruptedException e)  
          {  
           e.printStackTrace();  
         }  
       }  
    }  
    }  
      
    class Consumer implements Runnable{   //消費者  
       private SyncStack stack;  
      
       public Consumer(SyncStack stack) {  
       this.stack = stack;  
        }  
         
       public void run(){  
       for(int i = 0; i < stack.pro().length; i++){  
        String product = stack.pop();  
        System.out.println("消費了: "+product);  
        try{  
         Thread.sleep(1000);  
       }catch(InterruptedException e){  
         e.printStackTrace();  
         }  
        }  
       }  
    }  
      
    class SyncStack{   // 此類是(本質上:共同訪問的)共享數據區域  
    private String[] str = new String[10];  
        private int index;  
          
        public synchronized void push(String sst){ //供生產者調用  
        if(index == sst.length()){  
         try{  
          wait();  
         }catch(InterruptedException e){  
           e.printStackTrace();  
          }  
        }  
       this.notify(); //喚醒在此對象監視器上等待的單個線程  
       str[index] = sst;  
       index++;  
    }  
      
       public synchronized String pop(){   //供消費者調用  
        if(index == 0){  
         try{  
          wait();  
          }catch (InterruptedException e){  
           e.printStackTrace();  
          }  
       }  
        notify();  
        index--;  
        String product = str[index];  
        return product;  
       }  
      
        public String[] pro(){ //就是定義一個返回值爲數組的方法,返回的是一個String[]引用  
         return str;   //這是一個String[]引用  
       }  
    }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章