gghh######生產(chǎn)者消費(fèi)者問題是操作系統(tǒng)中的經(jīng)典問題,先用聲明Thread子類的方法來實(shí)現(xiàn)
問題:
顧客去包子店中買包子
包子每次只能生產(chǎn)一個(gè)只能消費(fèi)一個(gè)
包子有天津狗不理和無錫灌湯包兩類,價(jià)格分別是20元和10元。
蒸籠中沒有包子,店家才能生產(chǎn),否則等待。
蒸籠中有包子,顧客才能消費(fèi),否則等待。
請實(shí)現(xiàn)此過程
圖解.png
首先要設(shè)計(jì)類
- 包子是生產(chǎn)者和消費(fèi)者共有的,作為一類,包子的成員變量是其品牌,價(jià)格,存在狀態(tài),包子的存在狀態(tài)需要更改,所以要有一個(gè)get和set方法
- 生產(chǎn)者類:要有一個(gè)生產(chǎn)包子的方法,方法邏輯是有包子則等待,沒包子才生產(chǎn),生產(chǎn)完成了更改包子狀態(tài),通知消費(fèi)者
- 消費(fèi)者類類:要有一個(gè)消費(fèi)包子的方法,方法邏輯是有包子才消費(fèi),消費(fèi)完成后更改包子狀態(tài),通知生產(chǎn)者繼續(xù)生產(chǎn)包子
- 一個(gè)測試類,創(chuàng)建包子對象,包子是共享數(shù)據(jù),生產(chǎn)者消費(fèi)者需要知道包子的具體狀態(tài),所以生產(chǎn)者消費(fèi)者中需要有傳入包子對象的構(gòu)造方法
1. 先寫包子類
/**
* @author Joker
*/
public class BaoZi
{
String name;
int price;
boolean flag = false;
//獲取和設(shè)置包子的成員變量
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getPrice()
{
return price;
}
public void setPrice(int price)
{
this.price = price;
}
public boolean isFlag()
{
return flag;
}
public void setFlag(boolean flag)
{
this.flag = flag;
}
/**
* 包子的有參構(gòu)造方法,用于生產(chǎn)包子時(shí)創(chuàng)建相應(yīng)品牌價(jià)格的包子對象
*/
public BaoZi(String name, int price)
{
super();
this.name = name;
this.price = price;
}
/**
* 包子的無參構(gòu)造
*/
public BaoZi()
{
}
/**
* 生產(chǎn)包子方法,用于生產(chǎn)者調(diào)用,同步線程聲明synchronized 關(guān)鍵字
* 包子有不同的品牌和價(jià)格,所以需要傳入對應(yīng)的成員變量值
*/
public synchronized void produce(String name, int price)
{
if (flag)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//更改傳遞包子的屬性
this.name = name;
this.price = price;
//更改包子的狀態(tài)并通知消費(fèi)者
flag = true;
notify();
}
/**
* 消費(fèi)包子方法,用于消費(fèi)者調(diào)用,同步線程聲明synchronized 關(guān)鍵字
* 消費(fèi)者只能消費(fèi)生產(chǎn)者已經(jīng)生產(chǎn)好的包子,所以無需更改包子的成員參數(shù)
*/
public synchronized void consume()
{
if (!flag)
{
try
{
wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
//表明正在消費(fèi)何種包子(必須是剛才生產(chǎn)者已經(jīng)生產(chǎn)好的)
System.out.println("正在消費(fèi)" + getName() + ":" + getPrice() + "元");
//更改包子存在狀態(tài)并通知生產(chǎn)者繼續(xù)生產(chǎn)
flag = false;
notify();
}
}
2. 生產(chǎn)者類
public class Producer extends Thread
{
BaoZi baoZi;
/**
* @param 構(gòu)造方法接收包子對象進(jìn)行通信
*/
public Producer(BaoZi baoZi)
{
this.baoZi = baoZi;
}
@Override
public void run()
{
super.run();
// i計(jì)數(shù)來生產(chǎn)不同類型的包子,偶數(shù)次時(shí)生產(chǎn)天津狗不理
int i = 0;
while (true)
{
if (i % 2 == 0)
{
// 調(diào)用produce方法生產(chǎn)對應(yīng)的包子并輸出
baoZi.produce("天津狗不理", 10);
System.out.println("正在生產(chǎn)" + baoZi.getName() + ":" + baoZi.getPrice() + "元");
}
else
{
baoZi.produce("無錫灌湯包", 20);
System.out.println("正在生產(chǎn)" + baoZi.getName() + ":" + baoZi.getPrice() + "元");
}
i++;
}
}
}
3. 消費(fèi)者類
public class Consumer extends Thread
{
BaoZi baoZi;
/**
* 構(gòu)造方法 傳入baozi對象進(jìn)行通信
*/
public Consumer(BaoZi baoZi2)
{
baoZi = baoZi2;
}
@Override
public void run()
{
super.run();
while (true)
{
baoZi.consume();
}
}
}
4. 測試類
public class TestMain
{
public static void main(String[] args)
{
Baozi baozi = new Baozi(null, 0);
Producer producer = new Producer(baozi);
Customer customer = new Customer(baozi);
//啟動線程
producer.start();
customer.start();
}
}
5. 運(yùn)行結(jié)果
控制臺輸出.png