java多线程之生产者消费者

                     好久没写博客,今天将学习的多线程生产者消费者知识记录下来。

1.概括

                    多线程的生产者消费者场景需要三个类,生产者,消费者和仓库,生产者和消费者都是一个线程。

                   

2.生产者消费者场景描叙

                    生产者在生产产品:

                                  1.比较仓库中实际拥有的产品数量和最大容量的,如果实际拥有的产品数量等于最大容量,说明仓库已经满了,不能再生产了,生产者陷入等待状态。

                                  2.比较仓库中实际拥有的产品数量和最大容量的,如果实际拥有的产品数量小于最大容量,说明仓库还没有满,生产产品并告诉消费者可以消费产品了。

                    

                   消费者在消费产品:

                                  1.比较仓库中实际拥有的产品数量是否为0,如果等于0,说明仓库没有产品,不能再消费了,消费者陷入等待状态。

                                  2.比较仓库中实际拥有的产品数量是否为0,如果大于0,说明仓库还有产品,消费者消费产品,告诉生产者可以生产产品了。

                    这里有个疑问:当生产者陷入等待的时候,为什么不去通知消费者消费产品,消费者这个时候难道一定会去消费产品而不是也陷入等待吗?消费者这时是不会陷入等待的,他一定会去消费产品,只如为什么,请看下面的代码分析

3.生产者消费者代码分析

                   

/** 
 * @author  作者 wangbiao
 * @date 创建时间:2017年5月17日 下午3:36:21 
 * @parameter 
 * @return 
 */
public class ProductCostumerTest {
	public static void main(String args[]) throws InterruptedException{
		Cangku cangku = new Cangku();
		ProductThread productThread = new ProductThread(cangku,"生产者");
		CostumerThread costumerThread = new CostumerThread(cangku,"消费者者");
		costumerThread.start();
		Thread.sleep(1000);
		productThread.start();
		
	}

}
//仓库
class Cangku{
	private int count = 0;//仓库现在所拥有的苹果数量
	//消费方法
	public synchronized void pop(int i) throws InterruptedException{
		while(count<=0){
			System.out.println(Thread.currentThread().getName()+"等待中===================");
			//释放Cangku对象锁,当前线程进去等待状态
			this.wait();
		}
		System.out.println(Thread.currentThread().getName()+"消费了第"+i+"个苹果");
		count--;
		//释放Cangku对象锁,唤醒在此对象监视器上等待的某个线程 
		this.notify();
	}
	
	//生产方法
	public synchronized void push(int i) throws InterruptedException{
		while(count>=20){
			System.out.println(Thread.currentThread().getName()+"等待中===================");
			//释放Cangku对象锁,当前线程进去等待状态
			this.wait();
		}		
		count++;	
		System.out.println(Thread.currentThread().getName()+"生产了第"+i+"个苹果");
		//释放Cangku对象锁,唤醒在此对象监视器上等待的某个进程
		this.notify();
	}
}

//生产者
class ProductThread extends Thread{
	private Cangku cangku;
	public ProductThread(Cangku cangku,String threadName){
		super(threadName);
		this.cangku = cangku;
	}
	public void run(){
		for(int i=1;i<=20;i++){
			try {
				//让生产者停顿一下
				if(i==5){
					Thread.sleep(1000);
				}
				cangku.push(i);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

//消费者
class CostumerThread extends Thread{
	private Cangku cangku;
	public CostumerThread(Cangku cangku,String threadName){
		super(threadName);
		this.cangku = cangku;
	}
	public void run(){
		for(int i=1;i<=20;i++){
			try {
				cangku.pop(i);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
运行结果:

消费者者等待中===================
生产者生产了第1个苹果
生产者生产了第2个苹果
生产者生产了第3个苹果
生产者生产了第4个苹果
消费者者消费了第1个苹果
消费者者消费了第2个苹果
消费者者消费了第3个苹果
消费者者消费了第4个苹果
消费者者等待中===================
生产者生产了第5个苹果
生产者生产了第6个苹果
生产者生产了第7个苹果
生产者生产了第8个苹果
生产者生产了第9个苹果
生产者生产了第10个苹果
生产者生产了第11个苹果
生产者生产了第12个苹果
生产者生产了第13个苹果
生产者生产了第14个苹果
生产者生产了第15个苹果
生产者生产了第16个苹果
生产者生产了第17个苹果
生产者生产了第18个苹果
生产者生产了第19个苹果
生产者生产了第20个苹果
消费者者消费了第5个苹果
消费者者消费了第6个苹果
消费者者消费了第7个苹果
消费者者消费了第8个苹果
消费者者消费了第9个苹果
消费者者消费了第10个苹果
消费者者消费了第11个苹果
消费者者消费了第12个苹果
消费者者消费了第13个苹果
消费者者消费了第14个苹果
消费者者消费了第15个苹果
消费者者消费了第16个苹果
消费者者消费了第17个苹果
消费者者消费了第18个苹果
消费者者消费了第19个苹果
消费者者消费了第20个苹果

这里我特意让生产者在生产到第四个苹果的时候停顿了一下,此时,消费者线程占用cpu进行消费,将仓库里的四个苹果消费完后,消费者进入了等待,此时生产者继续生产苹果,然后消费者将生产者生产的16个苹果消费完。

至于前面提到的让生产者陷入等待后,消费者为什么不需要通知就回去消费产品,这是因为生产者陷入等待首先要满足的条件是仓库的产品已经满了,生产者在陷入等待的时候还会去释放对象锁,消费者进入运行状态,在调用消费方法的时候会拿到这个对象锁,而且仓库里是有产品的,所以就可以消费产品。

纸上得来终觉浅,绝知此事要躬行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值