首页 > 代码库 > java多线程之消费者生产者模式

java多线程之消费者生产者模式

  1. /*@author shijin 
  2. * 生产者与消费者模型中,要保证以下几点: 
  3. * 1 同一时间内只能有一个生产者生产     生产方法加锁sychronized 
  4. * 2 同一时间内只能有一个消费者消费     消费方法加锁sychronized 
  5. * 3 生产者生产的同时消费者不能消费     生产方法加锁sychronized 
  6. * 4 消费者消费的同时生产者不能生产     消费方法加锁sychronized 
  7. * 5 共享空间空时消费者不能继续消费     消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行 
  8. * 6 共享空间满时生产者不能继续生产     生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行    
  9. */  
  10.   
  11. //主类   
  12. class  ProducerConsumer  
  13. {  
  14.     public static void main(String[] args)   
  15.     {  
  16.         StackBasket s = new StackBasket();  
  17.         Producer p = new Producer(s);  
  18.         Consumer c = new Consumer(s);  
  19.         Thread tp = new Thread(p);  
  20.         Thread tc = new Thread(c);  
  21.         tp.start();  
  22.         tc.start();  
  23.     }  
  24. }  
  25.   
  26. //   
  27. class Mantou  
  28. {  
  29.     private int id;  
  30.       
  31.     Mantou(int id){  
  32.         this.id = id;  
  33.     }  
  34.   
  35.     public String toString(){  
  36.         return "Mantou :" + id;  
  37.     }  
  38. }  
  39.   
  40. //共享栈空间   
  41. class StackBasket  
  42. {  
  43.     Mantou sm[] = new Mantou[6];  
  44.     int index = 0;  
  45.       
  46.     /**  
  47.     * show 生产方法. 
  48.     * show 该方法为同步方法,持有方法锁; 
  49.     * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费; 
  50.     * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态, 
  51.     * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费 
  52.     * @param m 元素 
  53.     * @return 没有返回值  
  54.     */   
  55.   
  56.     public synchronized void push(Mantou m){  
  57.         try{  
  58.             while(index == sm.length){  
  59.                 System.out.println("!!!!!!!!!生产满了!!!!!!!!!");  
  60.                 this.wait();  
  61.             }  
  62.             this.notify();  
  63.         }catch(InterruptedException e){  
  64.             e.printStackTrace();  
  65.         }catch(IllegalMonitorStateException e){  
  66.             e.printStackTrace();  
  67.         }  
  68.           
  69.         sm[index] = m;  
  70.         index++;  
  71.         System.out.println("生产了:" + m + " 共" + index + "个馒头");  
  72.     }  
  73.   
  74.     /**  
  75.     * show 消费方法 
  76.     * show 该方法为同步方法,持有方法锁 
  77.     * show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产; 
  78.     * show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态 
  79.     * show 等消费结束释放同步方法锁后生产才能持有该锁进行生产 
  80.     * @param b true 表示显示,false 表示隐藏  
  81.     * @return 没有返回值  
  82.     */   
  83.     public synchronized Mantou pop(){  
  84.         try{  
  85.             while(index == 0){  
  86.                 System.out.println("!!!!!!!!!消费光了!!!!!!!!!");  
  87.                 this.wait();  
  88.             }  
  89.             this.notify();  
  90.         }catch(InterruptedException e){  
  91.             e.printStackTrace();  
  92.         }catch(IllegalMonitorStateException e){  
  93.             e.printStackTrace();  
  94.         }  
  95.         index--;  
  96.         System.out.println("消费了:---------" + sm[index] + " 共" + index + "个馒头");  
  97.         return sm[index];  
  98.     }  
  99. }  
  100.   
  101. class Producer implements Runnable  
  102. {  
  103.     StackBasket ss = new StackBasket();  
  104.     Producer(StackBasket ss){  
  105.         this.ss = ss;  
  106.     }  
  107.   
  108.     /**  
  109.     * show 生产进程.  
  110.     */   
  111.     public void run(){  
  112.         for(int i = 0;i < 20;i++){  
  113.             Mantou m = new Mantou(i);  
  114.             ss.push(m);  
  115. //          System.out.println("生产了:" + m + " 共" + ss.index + "个馒头");   
  116. //          在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱   
  117.             try{  
  118.                 Thread.sleep((int)(Math.random()*500));  
  119.             }catch(InterruptedException e){  
  120.                 e.printStackTrace();  
  121.             }  
  122.         }  
  123.     }  
  124. }  
  125.   
  126. class Consumer implements Runnable  
  127. {  
  128.     StackBasket ss = new StackBasket();  
  129.     Consumer(StackBasket ss){  
  130.         this.ss = ss;  
  131.     }  
  132.   
  133.     /**  
  134.     * show 消费进程. 
  135.     */   
  136.     public void run(){  
  137.         for(int i = 0;i < 20;i++){  
  138.             Mantou m = ss.pop();  
  139. //          System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头");   
  140. //  同上  在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱   
  141.             try{  
  142.                 Thread.sleep((int)(Math.random()*1000));  
  143.             }catch(InterruptedException e){  
  144.                 e.printStackTrace();  
  145.             }  
  146.         }  
  147.     }  
  148. }  

java多线程之消费者生产者模式