同步和多线程

问题描述 投票:0回答:1

我目前正在开发一个有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);
        }
        }
    });     
java multithreading synchronized
1个回答
0
投票

在某些方法中,您在Airport实例上进行同步,在其他方法中,您使用lanesOpen对象。这种方式,例如,如果使用addLaneOpen添加通道,则requestLane方法中的wait将永远不会得到通知。我认为您应该只在Airport对象上进行简单的同步,并在方法中添加notify,其中添加了一个lane。

一般来说,如果你得到一个threaddump(使用你的IDE,jstack或jvisualvm),你可以简单地找出你的问题。你会看到,你有什么线程,等待什么样的对象。然后你会立即找到你的bug。

© www.soinside.com 2019 - 2024. All rights reserved.