我有以下代码,两个线程检查堆栈中是否有元素,如果有,则将其弹出。由于某种原因,两个线程之一总是得到一个 java.util.EmptyStackException ,这意味着它弹出一个空堆栈。我的问题是不应该让这种方法同步来防止这种情况发生吗?是否可以仅使用同步方法来防止我的错误,或者我必须实现某种连接/倒计时/循环障碍/等?我问的原因是因为理想情况下我希望只有一个线程能够在任何给定时间访问堆栈板。
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
目标以提供更多信息。在每个线程抓取一个煎饼后,它会使用以下方法随机吃/睡一段时间。理想情况下,整个程序的目标是模拟生产者不断烹饪煎饼的位置,并将其添加到堆栈中。两个线程之一检查堆栈并在堆栈中有元素时抓取煎饼。这将一直发生,直到生产者线程完成煎饼。
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();
}