package com.shopping.test; public class ShaoKao { //串 String chuan; //肉 String rou; //烧烤的状态,初始状态为没有烧烤 boolean flag = false; public String getChuan() { return chuan; } public void setChuan(String chuan) { this.chuan = chuan; } public String getRou() { return rou; } public void setRou(String rou) { this.rou = rou; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }
下面是生产者
package com.shopping.test; /* * 注意: * 烧烤铺线程和吃货线程关系--->通信(互斥) * 必须使用同步技术保证两个线程只能有一个在执行 * 锁对象必须保证唯一,可以使用烧烤对象作为锁对象 * 烧烤铺类和吃货类就需要把烧烤对象作为参数传进去 * 1. 需要在成员位置创建一个烧烤变量 * 2. 使用带参数构造方法,为这个烧烤变量赋值 */ public class ShaoKaoPu extends Thread { //1. 需要在成员位置创建一个烧烤变量,作为锁对象 private ShaoKao bz; //2. 使用带参数构造方法,为这个烧烤变量赋值 public ShaoKaoPu(ShaoKao bz) { this.bz = bz; } //设置线程任务(run), 生产烧烤 public void run() { //定义一个变量,这个变量决定到底要做什么馅的烧烤 int count = 0; //死循环,让烧烤铺一直生产烧烤 while(true) { //必须使用同步技术保证两个线程只能有一个在执行 synchronized(bz) { //对烧烤的状态进行判断 if(bz.flag == true) { //已经有烧烤了,不用生产,烧烤铺调用wait方法进入等待状态 try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //被吃货唤醒之后,证明没有烧烤了,又要开始生产烧烤 //增加一些趣味性:交替生产烧烤 if(count % 2 == 0) { //生产 羊肉烤串 bz.chuan = "大串"; bz.rou = "羊肉"; }else { //生产 牛肉大葱馅 bz.chuan = "大串"; bz.rou = "羊肉"; } count++; System.out.println("烧烤铺正在生产:" + bz.chuan + bz.rou + "烧烤"); //生产烧烤需要3秒钟 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //烧烤铺生产好了烧烤,修改烧烤的状态为true有 bz.flag = true; //唤醒吃货线程起来吃烧烤 bz.notify(); //烧烤铺已经生产好了烧烤 System.out.println("烧烤铺已经生产好了" + bz.chuan + bz.rou + "烧烤" + "吃货可以开始吃了"); } } } }
消费者
package com.shopping.test; public class ChiHuo extends Thread{ //1. 需要在成员位置创建一个烧烤变量,作为锁对象 private ShaoKao bz; //2. 使用带参数构造方法,为这个烧烤变量赋值 public ChiHuo(ShaoKao bz) { this.bz = bz; } //设置线程任务(run), 吃烧烤 public void run() { //死循环,让吃货一直吃烧烤 while(true) { //必须使用同步技术保证两个线程只能有一个在执行 synchronized(bz) { //对烧烤的状态进行判断 if(bz.flag == false) { //发现没有烧烤,吃货调用wait方法进入等待状态,等烧烤铺做好烧烤 try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //被烧烤铺唤醒之后,证明有烧烤吃了 System.out.println("吃货正在吃:" + bz.chuan + bz.rou + "的烧烤"); //吃货吃完烧烤 //修改烧烤的状态为false没有 bz.flag = false; //吃货唤醒烧烤铺线程,继续生产烧烤 bz.notify(); System.out.println("吃货已经把:" + bz.chuan + bz.rou + "的烧烤吃完了"); System.out.println("---------------------------------------------------------------------------"); } } } }
测试:
package com.shopping.test; public class Test { public static void main(String[] args) { //创建烧烤对象,作为锁对象 ShaoKao bz = new ShaoKao(); //创建烧烤铺线程 new ShaoKaoPu(bz).start(); //开启吃货线程 new ChiHuo(bz).start(); } }
输出的是:
烧烤铺正在生产:大串羊肉烧烤
烧烤铺已经生产好了大串羊肉烧烤吃货可以开始吃了
吃货正在吃:大串羊肉的烧烤
吃货已经把:大串羊肉的烧烤吃完了
---------------------------------------------------------------------------
烧烤铺正在生产:大串羊肉烧烤
烧烤铺已经生产好了大串羊肉烧烤吃货可以开始吃了
吃货正在吃:大串羊肉的烧烤
吃货已经把:大串羊肉的烧烤吃完了
---------------------------------------------------------------------------
烧烤铺正在生产:大串羊肉烧烤
烧烤铺已经生产好了大串羊肉烧烤吃货可以开始吃了
吃货正在吃:大串羊肉的烧烤
吃货已经把:大串羊肉的烧烤吃完了
---------------------------------------------------------------------------