这个简单的练习有问题: 有一个停车区,一次最多允许4辆车,有6辆车。
问题是4辆车进入后,接下来的2辆车都处于等待状态,从未进入。
以下是我在屏幕上看到的内容:
Car 1 in
Car 2 in
Car 5 in
Car 6 in
Car 4 is waiting
Car 3 is waiting
Car 1 out
Car 1 in
Car 3 is waiting
Car 4 is waiting
Car 5 out
Car 5 in
Car 2 out
Car 2 in
and so on..
这里的课程:
public class Car extends Thread{
int idCar;
Monitor monitor;
public Car(int id, Monitor monitor){
idCar=id;
this.monitor=monitor;
}
public void run(){
while(true){
monitor.enter(idCar);
try{
sleep(2000);
}catch(Exception e){}
monitor.exit(idCar);
}
}
}
public class Monitor {
int maxSpots;
int parkedCars;
public Monitor(int maxSpots){
this.maxSpots=maxSpots;
parkedCars=0;
}
public synchronized void enter(int idCar){
while(parkedCars==maxSpots){
try{
System.out.println("Car "+idCar+" is waiting");
wait();
}catch(Exception e){}
}
++parkedCars;
System.out.println("Car "+idCar+" in");
notifyAll();
}
public synchronized void exit(int idCar){
/*while(parkedCars==0){ // i'm not sure if this check is needed, because
try{ // no car will ever get out, if it's not in.
wait();
}catch(Exception e){}
}*/
--parkedCars;
System.out.println("Car "+idCar+" out");
notifyAll();
}
}
public class Parking {
public static void main(String[] args){
Monitor m = new Monitor(4);
Car c1 = new Car(1, m);
Car c2 = new Car(2, m);
Car c3 = new Car(3, m);
Car c4 = new Car(4, m);
Car c5 = new Car(5, m);
Car c6 = new Car(6, m);
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
}
}
有人可以解释一下吗?
答案 0 :(得分:6)
您设计了代码,以便您的显示器不公平。
如果Car
退出插槽,它将进入循环中的下一步,因此它会立即尝试再次输入。在此期间,您的其他等待Car
被Thread.notifyAll()
唤醒
那些Thread
并不是最快的。他们不能保证不会拖延工作......
刚离开广告位的Car
会发生什么?它试图再次停放。由于它的线程没有等待,它不需要再次恢复工作......它立即停放
您可能需要的是队列。将您的请求Car
添加到Queue
,如果输入发生,请先通知您等待时间最长的Car
。正如Jan建议的那样,另一种方法是让那些退出Car
的人等待给其他游客一个机会。这可以通过在退出Thread.yield()
上使用Thread.sleep()
或Car
来实现(在完成退出后)。
您制作的这种情况对所有相关方都非常烦人。诚实的等待Car
正在等待他们的位置,而自我沉没的人永远不会回家;)