Java多线程同步:生产者与消费者

生产者与消费者问题问题是线程同步里边一个很经典的问题。

用通俗的语言来描述这个过程:

一群生产者不断的生产产品,并将产品放到一个容器里边;同时一群消费者不断从容器里边消费产品。

容器的容量是有限的。如果容器满了,生产者不能再往容器放产品,必须进入等待状态。等待产品被消费者拿走了,再往容器放产品。

同样,如果容器空了,消费者也必须进入等待状态。等待生产者往里边放产品,再将消费者唤醒。

java实现需要四个类:一个生产者,一个消费者,一个容器类,一个产品类。

这里以生产者生产面包为例

具体实现如下:

Bread.java (面包类,具体的产品实体)

public class Bread {
	private int id; //面包ID
	private int productId;//生产者ID
	public Bread(){
	}
	public Bread(int id,int productId){
		this.id = id;
		this.productId = productId;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getProductId() {
		return productId;
	}
	public void setProductId(int productId) {
		this.productId = productId;
	}
}
Basket.java(篮子,盛放面包的容器)

public class Basket {
	private Bread []breads = new Bread[10]; //存储生产的面包
	private int index = 0;//标记当前可用数组空间下标
	public synchronized void push(Bread b){
		System.out.println("生产者等待放入面包。。。。");
		while(index == breads.length){
			try{
				this.wait(); //如果篮子已满,使当前生产者线程等待
			}catch(InterruptedException ie){
				ie.printStackTrace();
			}
		}
		this.notify(); //唤醒一个生产者线程
		breads[index++] = b;
		System.out.println("生产者"+b.getProductId()+"生产了一个面包"+index);
	} 
	public synchronized void pop(int cid){
		System.err.println("消费者"+cid+"等待消费面包。。。。");
		while(index==0){
			try{
				this.wait();
			}catch(InterruptedException ie){
				ie.printStackTrace();
			}
		}
		this.notify();
		System.out.println(index+"面包被顾客"+cid+"消费!");
		index--;
	}
}
Producer.java(生产者,生产面包,继承了Thread类)

public class Producer extends Thread{
	private int id;
	private Basket basket;
	public Producer(int id,Basket basket){
		this.id = id;
		this.basket = basket;
	}
	
	@Override
	public void run(){
		for(int i=0;i<10;i++){
			Bread b = new Bread(i,id);
			basket.push(b);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
Customer.java(消费者,消费面包,继承了Thread类)

public class Customer extends Thread{
	private int id; //消费者Id
	private Basket basket;//消费对应的篮子的引用
	public Customer(int id,Basket basket){
		this.id = id;
		this.basket = basket;
	}
	
	@Override
	public void run() {
		for(int i=0;i<10;i++){
			basket.pop(id);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


Test.java (测试类)

public class Test {
	public static void main(String[] args) {
		Basket b = new Basket(); //创建一个篮子实例
		Producer p1 = new Producer(1, b);
		Producer p2 = new Producer(2, b);
		Customer c1 = new Customer(1, b);
		Customer c2 = new Customer(2, b);
		p1.start();
		p2.start();
		c1.start();
		c2.start();
	}
}

运行结果:

生产者等待放入面包。。。。
生产者1生产了一个面包1
1面包被顾客1消费!
消费者1等待消费面包。。。。
消费者2等待消费面包。。。。
生产者等待放入面包。。。。
生产者2生产了一个面包1
1面包被顾客2消费!
生产者等待放入面包。。。。
生产者1生产了一个面包1
消费者1等待消费面包。。。。
1面包被顾客1消费!
生产者等待放入面包。。。。
生产者2生产了一个面包1
生产者等待放入面包。。。。
生产者1生产了一个面包2
消费者1等待消费面包。。。。
2面包被顾客1消费!
消费者2等待消费面包。。。。
1面包被顾客2消费!
生产者等待放入面包。。。。
生产者1生产了一个面包1







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值