`
勤业思行
  • 浏览: 82143 次
  • 性别: Icon_minigender_1
  • 来自: 贵阳
社区版块
存档分类
最新评论

生产者消费者模型

    博客分类:
  • j2se
阅读更多

生产者—消费者问题:多线程访问的一个经典案例,即按面向对象的思想来分析问题的话,这个问题涉及四个对象,生产者Procedure、消费者Consumer、产品Product、仓库WareHouse。下面以一个简单的例子来进行实现。

一、产品Product

  每个产品有一个属性id,这个id值由生产者赋予。即生产者调用产品的构造方法来设置该属性id。

class Product
{  int id=0;
   Product(int id){
	this.id=id;}
	public String toString(){
	 return "Product: "+this.id;
	}
}

 

二、仓库WareHouse

 1、仓库有两个属性:库存num、容量,库存用int表示,初始化为0;容量用数组的长度表示。库存即该产品数组中的前num个产品。

2、两个方法:增加库存add和减少库存del。在add中将传入的产品参数放入库存数组,将库存量加一。减少库存del中将库存量num减一、并返回消费产品。

3、在add和del方法中,执行前后应该检查库存,若执行add方法,当库存为库存的容量时,使得当前线程wait,该线程(为生产者对象)放弃锁。直到当消费者线程执行del使得库存量小于仓库容量时,唤醒当前进程,重新获得锁,继续执行生产add。若执行del,当库存为0时,使得当前进程wait,释放锁,直到生产者进程获取锁之后执行add后库存大于0,此时唤醒进程重新获得锁,执行消费del。

4、在add和del方法中,可能出现多个生产者和多个消费者同时访问库存并执行add和del,所以这两个方法都应设置为同步方法。

class WareHouse
{   int num=0;
	Product[] list=new Product[10];
	public synchronized void add(Product p){
	while(num==list.length-1){
		try{this.wait();
		}catch(Exception e){
		e.printStackTrace();
		}
	}
	this.notifyAll();
	list[num]=p;
	num++;
	}
	public synchronized Product del(){
	while(num==0){
       try{this.wait();
		}catch(Exception e){
		e.printStackTrace();
		}
	}
	this.notifyAll();
   num--;
   return list[num];
	}
}
 

三、生产者Procedure

生产者构造方法传入一个WareHouse参数生成生产者。每个Produre都是一个进程,所以实现Runnable接口和相应的run方法,在run方法中,每个Procedure可以生产10件产品。

class Procedure implements Runnable
{  
	WareHouse wh=null;
   Procedure(WareHouse wh){
   this.wh = wh;}
	public void run(){
		for(int i=0;i<10;i++){
			Product pp =new Product(i);
		wh.add(pp);
		System.out.println(Thread.currentThread()+"生产了:"+pp);
		}
	}
}

 

四、消费者Consumer

消费者由传入一个WareHouse参数构造。同理,每个Consumer也实现了Runnable接口和run方法,在run方法中,设定每个消费者可以消费5件产品。

class Consumer implements Runnable
{  
	WareHouse wh=null;
   Consumer(WareHouse wh){
   this.wh = wh;} 
   public void run(){
	   for(int i=0;i<5;i++){
	   Product ppp= wh.del();
	   System.out.println(Thread.currentThread()+"消费了:"+ppp);
	   }
    }
}

 

五、测试类:在main方法中首先建立一个WareHouse对象,然后利用WareHouse对象新建Procedure对象和Consumer对象各俩,最后利用Procedure和Consumer对象新建四个进程,然后start这四个进程。

public class P_C
{
	public static void main(String[] args) 
	{   
		WareHouse wh =new WareHouse();
		Procedure p1=new Procedure(wh);
		Procedure p2=new Procedure(wh);
		
		Consumer m1 = new Consumer(wh);
		Consumer m2 =new Consumer(wh);

		Thread t1 =new Thread(p1);
		Thread t2 =new Thread(p2);
        
		Thread t3 =new Thread(m1);
		Thread t4 =new Thread(m2);

		t1.start();
		t2.start();
		t3.start();
		t4.start();

	}
}

 

  • P_C.rar (717 Bytes)
  • 下载次数: 12
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics