[Java]多线程之生产者消费者优化版
2015-06-08 15:27
711 查看
优化版,可以把生产和消费过程全部集中在baozi
里,生产者和消费者只需要下指令就好
![](http://img.blog.csdn.net/20150608152924337?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20150608152818729?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20150608152947051?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
重点是如何在baozi内实现两个方法:
对于生产者而言,true时没有包子,需要生产,生产完了,要通知正在等待的消费者,同时要置为false,表示已经有包子了,
False下,生产者就是要等待,等待消费者传来消息
对于消费者来说,false时有包子,可以去拿,拿了包子要通知生产者,置为true;true的状态下等生产者发来消息
![](http://img.blog.csdn.net/20150608153103684?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20150608153233550?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
OK,走起,出问题,一直在生产一种包子
![](http://img.blog.csdn.net/20150608153157982?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmpsZ28=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
有误版的资源池:
问题在哪?
生产者和消费者的线程谁先启动要看CPU的调度,具有随机性
假如生产者的线程先启动,此时生产狗不理,生产了要notify,而这个时候消费者的线程有可能还没起来,又去调度生产者,这个时候x自增了,变成1,按理说这个时候要生产猪扒包,但是这个时候flag还是true,因为没有消费者去置为false,也即是说生产者只能走到else的代码块里,在else里就只能等待,被挂起了,什么也做不了,那么这时候可以去调度消费者的线程,正好true可以拿,把flag置为false,并且通知生产者
这个时候生产者在else里被挂起,CPU调度他走起,什么也不做,直接退出了,相当于什么也没生产,又从头开始生产,还是狗不理。
有可能如此循环数次
逻辑上的错误,没就生产,有就等待,这并不是一个if-else的关系
如何修改?问题是出在消费者没启动从而使生产者进入挂起状态,那么现在就应该做到,即使消费者没启动,回来进生产者不是挂机而是依然判断一下,然后找消费者,直到消费者启动了,消费了这个包子,换个角度,一定要生产包子,然后等,等了之后一定还要生产,不能等完了就结束了。
那么,生产者的线程启动时,应该先判断是否是true,需要挂起,挂起了就转去消费者,即使这个时候消费者的线程依然没启动,回来还是在判断,判断了挂机,还是去找消费者,如此循环,直到消费者启动了。
同样,消费者也是先判断,是否是需要等待挂起,不需要等待才去拿包子
最终版资源池:
里,生产者和消费者只需要下指令就好
重点是如何在baozi内实现两个方法:
对于生产者而言,true时没有包子,需要生产,生产完了,要通知正在等待的消费者,同时要置为false,表示已经有包子了,
False下,生产者就是要等待,等待消费者传来消息
对于消费者来说,false时有包子,可以去拿,拿了包子要通知生产者,置为true;true的状态下等生产者发来消息
OK,走起,出问题,一直在生产一种包子
有误版的资源池:
package com.rjl.producerAndcustomer; public class Baozi { private String name; private int price; boolean flag=false; public synchronized void set(String name, int price){ if(!this.flag){ //true的时候要生产包子 this.name=name; this.price =price; //生产完了置为true this.flag=true; //通知 this.notify(); System.out.println("Producer set "+ this.name+" "+this.price ); } else { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public synchronized void get(){ //生产者生产了包子,flag为true,此时拿包子 if (this.flag) { System.out.println("Customer got "+ this.name+" "+this.price ); //拿了就置为false this.flag=false; //通知 this.notify(); } else { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
问题在哪?
生产者和消费者的线程谁先启动要看CPU的调度,具有随机性
假如生产者的线程先启动,此时生产狗不理,生产了要notify,而这个时候消费者的线程有可能还没起来,又去调度生产者,这个时候x自增了,变成1,按理说这个时候要生产猪扒包,但是这个时候flag还是true,因为没有消费者去置为false,也即是说生产者只能走到else的代码块里,在else里就只能等待,被挂起了,什么也做不了,那么这时候可以去调度消费者的线程,正好true可以拿,把flag置为false,并且通知生产者
这个时候生产者在else里被挂起,CPU调度他走起,什么也不做,直接退出了,相当于什么也没生产,又从头开始生产,还是狗不理。
有可能如此循环数次
逻辑上的错误,没就生产,有就等待,这并不是一个if-else的关系
如何修改?问题是出在消费者没启动从而使生产者进入挂起状态,那么现在就应该做到,即使消费者没启动,回来进生产者不是挂机而是依然判断一下,然后找消费者,直到消费者启动了,消费了这个包子,换个角度,一定要生产包子,然后等,等了之后一定还要生产,不能等完了就结束了。
那么,生产者的线程启动时,应该先判断是否是true,需要挂起,挂起了就转去消费者,即使这个时候消费者的线程依然没启动,回来还是在判断,判断了挂机,还是去找消费者,如此循环,直到消费者启动了。
同样,消费者也是先判断,是否是需要等待挂起,不需要等待才去拿包子
最终版资源池:
public class Baozi { private String name; private int price; boolean flag=false; //先判断是否需要挂起 public synchronized void set(String name, int price){ if( this.flag){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.name=name; this.price =price; this.flag=true; this.notify(); System.out.println("Producer set "+ this.name+" "+this.price ); } public synchronized void get(){ if (!this.flag) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("Customer got "+ this.name+" "+this.price ); this.flag=false; this.notify(); } }
相关文章推荐
- Java中同步与并发用法分析
- struts2使用session 的三种方式
- spring配置jdbc与hibernate数据源
- spring security源码分析之core包
- Java_获取当前月最后一天
- Java Project和Web Project
- Java实现冒泡排序
- java实现读取文件中的iP字段
- Struts2的文件上传和下载
- eclipse的注释模板
- Java中线程用法总结
- Eclipse打JAR包,插件FatJar安装与使用
- spring mvc 基于maven的完整demo
- 配置spring
- Java核心技术图
- Eclipse快捷键
- java POI操作Excel文件(合并单元格、插入图片、超链接)
- java基础二之基本数据类型
- java 、sql 时间格式化区别
- 《java短串的生成》