需求:某小區單元定制牛奶,送奶人員會將牛奶放入奶箱,該奶箱共能存放30瓶牛奶,居民從奶箱中取奶,請用程式實作這一程序
分析:
1.創建奶箱類:定義一個成員變數,表示是奶箱中的第幾瓶奶,提供存放牛奶和取出牛奶的方法
2.創建生產廠家類:實作Runable介面,重寫run方法,呼叫存放牛奶的方法
3.創建居民類:實作Runable介面,重寫run方法,呼叫取出牛奶的方法
4.創建測驗類:
1.創建奶箱物件
2.創建生產廠家物件,并將奶箱物件作為構造方法引數傳遞,呼叫存盤牛奶的方法
3.創建居民物件,并將奶箱物件作為構造方法引數傳遞,呼叫取出牛奶的方法
4.創建兩個執行緒,分別把生產廠家物件、居民物件作為構造方法引數傳遞
5.啟動執行緒
奶箱類
package Demo041902;
public class Box {
//定義一個成員變數,表示是奶箱中的第幾瓶奶,提供存放牛奶和取出牛奶的方法
private int milk;
//創建奶箱狀態,判斷是否為空
Boolean state=false;
//存放牛奶
public synchronized void put(int milk){
//先判斷奶箱是否為空,是:放奶入箱;否:休眠
if (state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//state=false,放奶入箱
this.milk=milk;
System.out.println("生產廠家將第"+this.milk+"瓶奶放入奶箱");
//修改狀態
state=true;
//喚醒執行緒
notifyAll();
}
public synchronized void get(){
//判斷奶箱是否為空,空的就休眠
if (!state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//奶箱不空,就取奶
System.out.println("居民取出第"+this.milk+"瓶奶");
//取完后修改狀態
state=false;
//喚醒執行緒
notifyAll();
}
?
}
生產廠家類
package Demo041902;
public class producter implements Runnable {
private Box b;
public producter(Box b) {
this.b=b;
}
//實作Runable介面,重寫run方法,呼叫存放牛奶的方法
@Override
public void run() {
for (int i=1;i<=5;i++){
b.put(i);
}
}
}
消費者類
package Demo041902;
public class consumer implements Runnable{
private Box b;
public consumer(Box b) {
this.b=b;
}
//實作Runable介面,重寫run方法,呼叫取出牛奶的方法
@Override
public void run() {
while(true){
b.get();
}
}
}
測驗類
package Demo041902;
public class Demo {
public static void main(String[] args) {
//創建奶箱物件
Box b=new Box();
//創建生產廠家物件,并將奶箱物件作為構造方法引數傳遞,呼叫存盤牛奶的方法
producter p=new producter(b);
//創建居民物件,并將奶箱物件作為構造方法引數傳遞,呼叫取出牛奶的方法
consumer c=new consumer(b);
//創建兩個執行緒,分別把生產廠家物件、居民物件作為構造方法引數傳遞
Thread t=new Thread(p,"生產者");
Thread t1=new Thread(c,"消費者");
t.start();
t1.start();
}
}
容易出現的問題:
1.不判斷奶箱的狀態,會出現一直取最后一瓶奶
2.IllegalMonitorStateException:拋出以表示執行緒已嘗試在物件的監視器上等待或通知其他執行緒等待物件的監視器,而不擁有指定的監視器,執行緒沒有同步會拋出這個例外,需要在方法上加同步鎖
3.去除第一瓶奶后不往下走,執行緒休眠后沒有喚醒
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/458669.html
標籤:其他
下一篇:Java基礎——網路編程
