您的位置:首页 > 编程语言 > Java开发

[Java]多线程之生产者消费者优化版

2015-06-08 15:27 711 查看
优化版,可以把生产和消费过程全部集中在baozi
里,生产者和消费者只需要下指令就好







重点是如何在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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: