我目前正在开发一个有2个车道的机场应用程序,但我对飞机着陆有问题。如果只有一条车道工作,一切正常,但如果我增加一条车道,飞机一次降落一架,同时它们应该同时落在两条车道上。我已经尝试使用System.out来查看问题所在,但是,这没有什么帮助。如果你们能帮我看看我做错了什么,我会非常感激。谢谢,这是相关的代码(我知道它有点多):
public class Airport{
private List<Lane> lanesOpen = new ArrayList<Lane>();
private List<AirplaneThread> airplanes;
public void start(){
for(AirplaneThread airplane : airplanes){
if(airplane.getState()==Thread.State.NEW)
airplane.start();
}
}
public void open(List<AirplaneThread> airplanes) {
this.airplanes = airplanes;
}
public synchronized void requestLane(){
while(getLanesAvailable().size()==0 && airplanes.size()==0 ){
try {
wait();
} catch (InterruptedException e) { }
}
List<Lane> lanes = getLanesAvailable();
for(Lane lane: lanes){
if(airplanes.size()>0){
AirplaneThread airplane = airplanes.remove(0);
airplane.land(lane);
}
}
notifyAll();
}
public synchronized void landingIsOver(Lane lane){
while(!lane.isClear()){
try{
wait();
}catch(InterruptedException e){
}
}
lane.getText().setText("");
notifyAll();
}
public List<Lane> getLanesAvailable(){
List<Lane> lanes = new ArrayList<>();
synchronized(lanesOpen){
for(Lane l : lanesOpen){
if(l.isClear())
lanes.add(l);
}
}
return lanes;
}
public void addLaneOpen(Lane lane){
synchronized(lanesOpen){
lanesOpen.add(lane);
}
}
public void removeLane(Lane l){
synchronized(lanesOpen){
Iterator<Lane> iterator = lanesOpen.iterator();
while(iterator.hasNext()){
Lane lane = iterator.next();
if(lane.getNumber()==l.getNumber())
iterator.remove();
}
}
}
public class AirplaneThread extends Thread implements AirplaneModel {
protected final String name;
protected final int capacity;
protected int fuel;
protected final int consumption;
protected boolean hasLanded;
protected final int LANDING_TIME;
protected Airport airport;
public AirplaneThread(String name, int capacity, int fuel, int consumption, int LANDING_TIME, Airport airport){
this.name = name;
this.capacity = capacity;
this.fuel = fuel;
this.consumption = consumption;
this.LANDING_TIME = LANDING_TIME;
this.hasLanded = false;
this.airport = airport;
}
@Override
public void run() {
while(!hasLanded){
airport.requestLane();
}
}
public synchronized void land(Lane lane){
try{
lane.changeState(false);
lane.getText().setText(toString());
airport.notifyOut(3);
sleep(LANDING_TIME);
hasLanded = true;
lane.changeState(true);
airport.landingIsOver(lane);
}catch(InterruptedException e){ }
}
}
public class Lane {
private JTextField plane;
private JCheckBox open;
private boolean isclear;
private int number;
public Lane(JTextField plane, JCheckBox open, JLabel label, int number){
this.plane = plane;
this.open = open;
this.isclear = false;
this.number = number;
}
public void changeState(boolean state){
this.isclear = state;
}
public boolean isClear(){
return isclear;
}
}
每当我在GUI中打开一个通道时,我也有这个代码用于哨兵:
laneB.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//basically this returns the lane which checkbox i clicked
Lane lane = CenterPanel.getLanes().get(j-1);
if(lane.getCheck().isSelected()){
airport.removeLane(lane);
lane.close();
}else{
lane.open();
airport.start();
airport.addLaneOpen(lane);
}
}
});
在某些方法中,您在Airport实例上进行同步,在其他方法中,您使用lanesOpen对象。这种方式,例如,如果使用addLaneOpen添加通道,则requestLane方法中的wait将永远不会得到通知。我认为您应该只在Airport对象上进行简单的同步,并在方法中添加notify,其中添加了一个lane。
一般来说,如果你得到一个threaddump(使用你的IDE,jstack或jvisualvm),你可以简单地找出你的问题。你会看到,你有什么线程,等待什么样的对象。然后你会立即找到你的bug。