私はマルチスレッドについていくつかの研究を行っており、プログラムを作成しようとしています。
複数の顧客に並行してサービスを提供することをシミュレートするレストラン プログラムを作成しました。
- レストランが開き、ウェイター、シェフ、何人かの顧客を作成し、すべての顧客が食事を食べるまで待ちます
- 顧客が注文し、ブール値の「食べられる」が真になるのを待ってから、レストランに通知します
- ウェイターはクライアントが注文するのを待ってから、シェフに通知します
- シェフは、ウェイターが注文について彼に通知するのを待ち、食事を準備し、顧客の「食べた」をtrueに設定します
どういうわけか、私のプログラムはほぼ異なる結果で終了します。
私が行った調査の後、別の方法で終了する 2 つの理由がわかりました。1) メソッドが同期されていない場合 (私のプログラムではそうではありません)。2) スレッドのリソースの割り当て方法に影響を与えることはできませんが、スレッドのシーケンスに小さな違いが生じるためです。
しかし、私のプログラムは、スレッドのシーケンスの小さな違いだけでなく、大きな違いで終了します。
- 顧客が 1 人の場合、常に正しく終了します。
- 複数の顧客がいる場合、すべてがうまくいき、レストランが閉まることがあります。しかし、シェフが次の注文を受けるべき瞬間に、ウェイターによる2回目の通知の後にスタックすることがあります。終了せず、スレッドは実行されていますが、シェフは次の注文を処理しません。
誰かが私にヒントを教えてもらえますか?
シェフのコード:
class Chef extends Thread{
private static int _id=1;
private int id;
Order order;
public Chef(){
this.id=_id;
_id++;
order=null;
this.start();
}
@Override
public void run() {
System.out.println("Chef ("+id+") starts to work...");
synchronized(this){
while(order==null){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Chef ("+id+") prepared Order ("+this.order.getId()+")");
Restaurant.customers.get(this.order.getId()-1).served=true;
synchronized(Restaurant.customers.get(this.order.getId()-1)){
Restaurant.customers.get(this.order.getId()-1).notify();
}
order=null;
}
public void prepareOrder(Order order){
this.order=order;
System.out.println("Chef ("+this.id+") prepares order ("+order.getId()+")");
synchronized(this){
this.notify();
}
}
}
ウェイターのコード (正常に動作し、常に注文を処理します):
class Waiter extends Thread{
private static int _id=1;
private int id;
Order order;
public Waiter(){
this.id=_id;
_id++;
order=null;
this.start();
}
@Override
public void run() {
System.out.println("Waiter ("+this.id+") starts to work...");
synchronized(this){
while(takenOrder==false){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
order=null;
Restaurant.chefs.get(0).prepareOrder(order);
}
public void takeOrder(Order order){
this.order=order;
System.out.println("Waiter ("+this.id+") takes order ("+this.order.getId()+")");
synchronized(this){
this.notify();
}
}
}