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

来源:互联网 发布:网络拨号图标不见了 编辑:程序博客网 时间:2024/06/06 01:18
/*@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

0 0