java多线程之生产者消费者

来源:互联网 发布:无线mac地址修改器 编辑:程序博客网 时间:2024/06/06 03:34

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

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个苹果消费完。

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

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

原创粉丝点击