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(); } }
輸出的是:
燒烤鋪正在生產:大串羊肉燒烤
燒烤鋪已經生產好了大串羊肉燒烤吃貨可以開始吃了
吃貨正在吃:大串羊肉的燒烤
吃貨已經把:大串羊肉的燒烤吃完了
---------------------------------------------------------------------------
燒烤鋪正在生產:大串羊肉燒烤
燒烤鋪已經生產好了大串羊肉燒烤吃貨可以開始吃了
吃貨正在吃:大串羊肉的燒烤
吃貨已經把:大串羊肉的燒烤吃完了
---------------------------------------------------------------------------
燒烤鋪正在生產:大串羊肉燒烤
燒烤鋪已經生產好了大串羊肉燒烤吃貨可以開始吃了
吃貨正在吃:大串羊肉的燒烤
吃貨已經把:大串羊肉的燒烤吃完了
---------------------------------------------------------------------------