消费者和生产者问题演示之吃包子demo
简单介绍
本例采用包子类BaoZi作为缓冲区,BaoZiPu为包子铺线程类,即为生产者,ChiHuo为吃货线程类,即为消费者。
吃包子问题逻辑分析
顾客来包子铺买包子,说“老板,来二两包子。”(程序开始,包子类即缓冲区为空,have为false),于是顾客开始打盹。(起得早没睡醒,此为消费者阻塞 bz.wait())
老板:“好的,客官请稍等,马上来。”(经判断,没有包子即have为false,消费者唤醒生产者,让老板做2秒,即Thread.sleep(2000),至于为什么不先做包子,可以认为此包子铺主打鲜味,让顾客看到制作过程,让顾客吃的放心)
老板:“包子做好了,客官请慢用。”(老板做好某馅的包子,have变为true,count = 1 - count,count运算用于换一个口味的包子,bz.notify()唤醒消费者,)
顾客:“老板,你这包子又白又大,看起来真好吃呀。”(经判断,有包子即have为true,顾客开始吃包子)
顾客:“老板你这包子,真好吃又管饱,下次还来啊,记得给我换个口味。”(此为剧情需要,嘻嘻)
这就是包子铺的一次买卖包子过程。同时,在顾客说要买包子之后,老板要判断包子有没有,如果有,就阻塞 bz.wait()。可以理解成老板的蒸炉一次只能放一个,两个放不下,即可以理解成缓冲区长度为1。
接下来上“才艺”
温馨提示:运行之后等待6-8秒后记得暂停程序的运行哦。
包子类
package ChiBaoZiDemo;
public class BaoZi {
String pi;
String xian;
boolean have = false;
}
包子铺类
package ChiBaoZiDemo;
public class BaoZiPu extends Thread {
private BaoZi bz;
public BaoZiPu(){
}
public BaoZiPu(BaoZi bz){
this.bz = bz;
}
@Override
public void run() {
int count = 0;
while(true){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(bz){
System.out.println("好的,请稍等");
if(!bz.have){
if(0 == count){
bz.pi = "薄皮";
bz.xian = "三鲜馅";
}else{
bz.pi = "冰皮";
bz.xian = "牛肉大葱馅";
}
bz.have = true;
count = 1 - count;
System.out.println("做好了"+bz.pi+bz.xian+"包子");
bz.notify();
}else{
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
吃货类
package ChiBaoZiDemo;
public class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo() {
}
public ChiHuo(BaoZi bz){
this.bz = bz;
}
@Override
public void run() {
while(true){
synchronized (bz){
if(!bz.have){
System.out.println("老板我要xxx包子");
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("吃"+bz.pi+bz.xian+"包子");
bz.have = false;
bz.notify();
System.out.println("吃完了"+bz.pi+bz.xian+"包子");
System.out.println("============================");
}
}
}
}
}
主函数
package ChiBaoZiDemo;
public class MainDemo {
public static void main(String[] args) {
BaoZi bz = new BaoZi();
new BaoZiPu(bz).start();
new ChiHuo(bz).start();
}
}
两次相邻的运行结果