//////////////////////////////////////////////////
// //
//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();
/**/ }
}
// //
//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();
/**/ }
}
我觉得应该把这一步同步化
synchrnoize Producer(Storage s){
this.s=s;
}
1、多个线程操作occupiedBufferCount,必须放到同步代码块中;写的同步了,但读和写没同步上。2、
//定义这个静态变量,为了是生产者的产品编号统一,但事与愿违,竟 //
//出现两个生产者都生产了一号产品的问题。我是想让它三个生产者都统一 //
//他们生产出来的产品的编号,总共60个产品,编号就是从1到60,但 //
//出现一号产品被几个生产者都生产了(请试着运行就可看到问题)。我是觉得 //
//这样实现没错,但究竟错在哪里,要怎么改,才能实现统一产品的编号???// 你定义一个静态变量,然后几个生产者去同时修改它(p1改成1,++变成2,p2又改成1,++变成2,p3又改成1,++又变成2 ),谁知道你要干嘛?
你总共生产60个产品,不是用for这样写的,这样是每个producer都生产了60个。
定义一个同步变量,每个producer去同步读它,如果没有到60,就把它++,如果到了60就退出。
不可以对构造函数设置同步synchonized!这是不可行的。
回复chief_fu :谢谢指出这个问题,更改后,仍不是问题所在
改成
i++