//////////////////////////////////////////////////
//                                              //
//3个生产者3个消费者,6个缓冲区的情况   //
//  作者:cavonchen                             //
//  时间:五月一日                                  //
///////////////////////////////////////////////// 
class Product{//定义产品类
 int id=0;
 Product(int id){
  this.id=id;
 } }
class Storage{//定义仓库  int occupiedBufferCount=0;//说明仓库放满的数目,刚开始全是空的,一个产品也没放
 Product[] buffer=new Product[6];//创建6个缓冲区,用来放产品 //c++中,用p、v操作来实现同步与互斥,在java中,用synchronized来实现同步,
 
 public synchronized void push(Product m){//同步方法,仓库中的放东西方法
  while(occupiedBufferCount==buffer.length){//生产者要放东西,当通通放满时,必须等待,
   try{
    System.out.println(
     Thread.currentThread().getName()+"  tries to produce,but it's full,only to wait");
    this.wait();
   }catch(InterruptedException e){
    System.out.println("Throw InterrupedEXception");
    e.printStackTrace();
   }//有可能抛出异常,必须对它进行捕捉
  }
  
  notifyAll();//如果没有满,则生产者顺利放入产品   buffer[occupiedBufferCount]=m;
  occupiedBufferCount++;  }
 
 public synchronized Product get(){
  while(occupiedBufferCount==0){//消费者要拿东西,却发现什么都没有
   try{
    System.out.println(
     Thread.currentThread().getName()+"  tries to consumer,but it's nothing,only to wait");
    this.wait();
   }catch(InterruptedException e){
    System.out.println("Throw InterrupedEXception");
    e.printStackTrace();
   }//有可能抛出异常,必须对它进行捕捉
  }
  occupiedBufferCount--;   notify();//若成功拿取,则把空位置的数目减1,并返回产品   return buffer[occupiedBufferCount];
 }
} class Producer implements Runnable{//定义生产者线程
 Storage  s;//声明生产者要放产品的仓库
 Producer(Storage s){
  this.s=s;      ////////////////////////////////////////////////////////////////////////////////////
                      //                                我的问题:                                       //
 }                   //                                                                                                               //
 static int i=0;//定义这个静态变量,为了是生产者的产品编号统一,但事与愿违,竟         //
                     //出现两个生产者都生产了一号产品的问题。我是想让它三个生产者都统一   //
                     //他们生产出来的产品的编号,总共60个产品,编号就是从1到60,但        //
                    //出现一号产品被几个生产者都生产了(请试着运行就可看到问题)。我是觉得   //
                    //  这样实现没错,但究竟错在哪里,要怎么改,才能实现统一产品的编号???//
                    //                                                                                                                  //
                    ////////////////////////////////////////////////////////////////////////////////////
 public void run(){//定义一个新线程必须重写父类的run方法   for( i=1;i<=60;i++){
   Product m=new Product(i);//生产20个产品
   s.push(m);
   System.out.println(
    Thread.currentThread().getName()+"生产了"+m.id+" 总数:"+s.occupiedBufferCount);
  
   try{
       Thread.sleep((int)(Math.random()*200));//这里的休眠时间越短用来模拟它生产的越快
      } catch(InterruptedException e){
       e.printStackTrace();
      } 
     }
 }
} class Consumer implements Runnable{
 Storage s;
 Consumer(Storage s){
  this.s=s;
 }
 
 public void run(){   for(int j=0;j<20;j++){
   Product m= s.get();
   System.out.println(
    Thread.currentThread().getName()+"消费了"+m.id+" 总数:"+s.occupiedBufferCount);
  
   try{
       Thread.sleep((int)(Math.random()*1000));//这里的休眠时间越长用来模拟它生产的越慢
      }catch(InterruptedException e){
       e.printStackTrace();
      }
     }
 }
} public class ProducerAndConsumer{
 public static void main(String[] args){
  Storage s=new Storage();
  Producer p=new Producer(s);
  Consumer c=new Consumer(s);
  new Thread(p,"producer1").start();
  new Thread(c,"consumer1").start();
//下面的是用来模拟多线程,这样总共有三个生产者,三个消费者   new Thread(p,"producer2").start();
  new Thread(c,"consumer2").start();
  new Thread(p,"producer3").start();
  new Thread(c,"consumer3").start();
  
    /**/  }
}

解决方案 »

  1.   

    Product m=new Product(i);//生产20个产品 
    我觉得应该把这一步同步化
      

  2.   

    同意二楼说的,将Producer的构造方法改成下边这样试试
     synchrnoize Producer(Storage s){ 
      this.s=s;
     }  
      

  3.   

    问题有两个:
    1、多个线程操作occupiedBufferCount,必须放到同步代码块中;写的同步了,但读和写没同步上。2、
    //定义这个静态变量,为了是生产者的产品编号统一,但事与愿违,竟         // 
    //出现两个生产者都生产了一号产品的问题。我是想让它三个生产者都统一   // 
    //他们生产出来的产品的编号,总共60个产品,编号就是从1到60,但        // 
    //出现一号产品被几个生产者都生产了(请试着运行就可看到问题)。我是觉得   // 
    //这样实现没错,但究竟错在哪里,要怎么改,才能实现统一产品的编号???// 你定义一个静态变量,然后几个生产者去同时修改它(p1改成1,++变成2,p2又改成1,++变成2,p3又改成1,++又变成2 ),谁知道你要干嘛?
    你总共生产60个产品,不是用for这样写的,这样是每个producer都生产了60个。
    定义一个同步变量,每个producer去同步读它,如果没有到60,就把它++,如果到了60就退出。
      

  4.   

    更正一下:不是每个producer都是60个,是三个加起来超过了60。
      

  5.   

    回复二楼的风亦飞:
       不可以对构造函数设置同步synchonized!这是不可行的。
    回复chief_fu :谢谢指出这个问题,更改后,仍不是问题所在
      

  6.   

    把for循环中的i=0
    改成
    i++