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 }

 

posted @ 2013-08-19 10:25  幻星宇  阅读(448)  评论(2编辑  收藏  举报