生產者模式實現總結1


前言

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

一、方式1

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

(有一篇講解多線程的非常有名的博客,建議初學多線程的朋友多關注一下,總結網址為:http://lavasoft.blog.51cto.com/62575/27069,順便感謝一下這些大牛們為吾等小白掃盲!)

生產者-消費者模型准確說應該是“生產者-消費者-倉儲”模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。
對於此模型,應該明確一下幾點:
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[]引用  
       }  
    }  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM