多线程基础部分之生产消费者案例

      

在资源的同步与互斥问题中,最经典的就是“生产者-消费者”问题。生产者-消费者问题的具体含义:系统中有很多生产者和消费者并发的工作,生产者负责生产资源,消费者负责消费资源,当消费者消费资源时,如果资源不足则需要等待;反之当生产者圣餐资源时,如果资源充足,则也需要等待。并且同一时刻只能一个生产者或消费者进行操作。


下面给出具体的代码:

package test11;

public class BreadContainer {
	//资源容器最大容量
	public static final int MAXNUM = 300;
	//资源当前资源的数量
	private int num;
	
	public BreadContainer(){};
	
	
	
	 public synchronized void produceBread(int produceNum, String producerName) {
		while(produceNum + num > MAXNUM){
			System.out.println("资源充足,不需要生产!"+producerName+" 去等待。。。");
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//刷新当前资源数量
		num = num +produceNum;
		System.out.println(producerName+"生产了"+produceNum+"数量的资源"+",现在共有"+num+"数量的资源!");
		//唤醒资源等待池中的所有线程
		notifyAll();
		
	}

	public synchronized void consumeBread(int consumeNum, String consumerName) {
		while(consumeNum > num){
			System.out.println("资源不足,不能消费!"+consumerName +"去等待。。。");
			try {
				this.wait();
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
		}
		//刷新当前资源数量
		num = num -consumeNum;
		System.out.println(consumerName+"消费了"+consumeNum +"数量的资源"+",现在共有"+num+"数量的资源!");
		//唤醒资源等待池中的所有线程
		notifyAll();
		
	}

}

注意: 用于生产、消费的同步方法要写在资源中,而不是生产者或消费者的线程中,因为要锁定的是资源对象。需要锁定哪个对象,同步方法就位于哪个对象中。


package test11;

public class Producer extends Thread{
	//生产者需要访问的面包容器资源
	private BreadContainer bc;
	//生产者一次需要生产的面包数量
	private int produceNum;
	public Producer(){}
	public Producer(String name,int produceNum,BreadContainer bc){
		this.produceNum = produceNum;
		this.bc = bc;
		this.setName(name);
	}
	@Override
	public void run() {
		//调用资源容器的同步方法生产资源
		bc.produceBread(produceNum,this.getName());
	}
	
}

package test11;

public class Consumer extends Thread{
	private int consumeNum;
	private BreadContainer bc;
	public Consumer(){}
	public Consumer(String name,int consumeNum,BreadContainer bc){
		this.consumeNum = consumeNum;
		this.bc = bc;
		this.setName( name);
		
	}
	@Override
	public void run() {
		//调用资源容器的同步方法消费资源
		bc.consumeBread(consumeNum,this.getName());
	}
	
}

package test11;

public class Main {
	public static void main(String[] args) {
		BreadContainer bc = new BreadContainer();
		Thread p1 = new Producer("p1", 50, bc);
		Thread p2 = new Producer("p2", 150, bc);
		Thread p3 = new Producer("p3", 100, bc);
		Thread c1 = new Consumer("c1", 100, bc);
		Thread c2 = new Consumer("c2", 150, bc);
		p1.start();
		p2.start();
		p3.start();
		c1.start();
		c2.start();
		

	}
}

运行结果:

p1生产了50数量的资源,现在共有50数量的资源!
资源不足,不能消费!c2去等待。。。
资源不足,不能消费!c1去等待。。。
p3生产了100数量的资源,现在共有150数量的资源!
p2生产了150数量的资源,现在共有300数量的资源!
c1消费了100数量的资源,现在共有200数量的资源!
c2消费了150数量的资源,现在共有50数量的资源!

 注意:在同步方法中调用的时资源对象的wait方法,让执行同步方法线程去资源的资源等待池中等待。同时,调用的notifyAll方法也是资源对象的,功能时通知资源等待池中的线程出来恢复工作。wait()方法释放锁,而notifyAll()不释放锁,只是起到通知作用,因此即使执行了notifyAll()该语句,锁也不会释放,只有等到任务执行完,锁才会释放。在资源等待池中的线程是没有顺序的,notify()方法只是从资源等待池中任意的选择一个线程唤醒,并不指定恢复哪一个。当多线程访问同一资源时,建议使用notifyAll()唤醒所有线程。

未完待续。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值