I'm currently working on an Airport app with 2 lanes, but I have a problem with the planes landing. If there is only one lane working everything works fine but if I add a lane, the planes land one at a time, when they should be landing on both the lanes at the same time. I've tried using System.out to see where the problem was but, that was of little help. If you guys could help me see what I'm doing wrong I would be very thankful. Thanks and here is the relevant code(I know it's a bit much):
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;
}
}
And i also have this code for a sentinel whenever i open a lane in my 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);
}
}
});