私は次のコードを持っています。2つのスレッドがスタックに要素があるかどうかをチェックし、ある場合はそれをポップします。何らかの理由で、2つのスレッドの1つは常にjava.util.EmptyStackExceptionを取得します。これは、空のスタックをポップすることを意味します。私の質問は、このメソッドを同期させることでこれを防ぐべきではないかということです。また、同期されたメソッドを使用するだけでエラーを防ぐことは可能ですか、それとも何らかの結合/カウントダウンラッチ/サイクリックバリエなどを実装する必要がありますか?私が尋ねている理由は、理想的には、常に1つのスレッドだけがスタックプレートにアクセスできるようにしたいからです。
public synchronized void checkPlate(){
//System.out.println(this.name + " checks the plate for pancake");
Boolean isEmpty = Producer.plate.isEmpty();
if ( isEmpty == false){
System.out.println(this.name + " grabs a pancake");
Producer.plate.pop();
eat();
this.eatenPancakes +=1;
}else{
try {
Thread.sleep(200);// waits one minute seconds instead of minutes
checkPlate();
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
更新
提案の後、このコードを使用してプロデューサープレートに同期ブロックを実装してみることにしました。そうすると、すべてのスレッドがフリーズしたように見えます。この同期されたブロックをプロデューサーオブジェクト/スレッドにも追加する必要がありますか?
public void checkPlate(){
//System.out.println(this.name + " checks the plate for pancake");
synchronized (Producer.plate){
Boolean isEmpty = Producer.plate.isEmpty();
if ( isEmpty == false){
System.out.println(this.name + " grabs a pancake");
Producer.plate.pop();
eat();
this.eatenPancakes +=1;
}else{
try {
Thread.sleep(200);// waits since theres no pancake
checkPlate();
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
より多くの情報を提供するために2つの目標を更新します。各スレッドがパンケーキをつかんだ後、次の方法でランダムな時間食べたり寝たりします。理想的には、プログラム全体の目標は、プロデューサーが絶えずパンケーキを調理してスタックに追加する場所をシミュレートすることです。2つのスレッドの1つがスタックをチェックし、スタックに要素がある場合はパンケーキを取得します。これは、プロデューサースレッドがパンケーキの調理を終了するまで発生します。
public void eat(){
Random ran = new Random();
double eatingTime;
if (this.name == "Piggy"){
eatingTime = ran.nextDouble() * (4 - 2) + 2; //generates a value between 2 and 4
}else{
eatingTime = ran.nextDouble() * (5 - 3) + 3; //generates a
}
try {
System.out.println(this.name + " starts eating a pancake...");
Thread.sleep((long)eatingTime *100);//mili seconds instead of minutes
Boolean isEmpty = Producer.plate.isEmpty();
if (Producer.finished == false && isEmpty == false){
checkPlate();
}
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}