【问题标题】:Synchronization and multithreading同步和多线程
【发布时间】:2016-12-07 18:23:24
【问题描述】:

我目前正在开发一个有 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);
        }
        }
    });     

【问题讨论】:

  • 引用 Brian Goetz 的话:“编写并发程序比编写单线程程序更难,因为可能出错的事情更多,而且错误更难检测。”

标签: java multithreading synchronized


【解决方案1】:

在某些方法中,您在 Airport 实例上进行同步,在其他方法中,您使用 lanesOpen 对象。这样,例如,如果您使用 addLaneOpen 添加通道,requestLane 方法中的等待将永远不会收到通知。我认为您应该在任何地方的 Airport 对象上简单地同步,并将 notify 添加到添加车道的方法中。

通常,如果您得到一个线程转储(使用您的 IDE、jstack 或 jvisualvm),您可以简单地找出问题所在。你会看到,你有什么线程,在等待什么样的对象。然后您会立即找到您的错误。

【讨论】:

  • 谢谢,我试试看。
  • 是的,那样会导致线程锁定,但我会尝试使用 IDE 找出导致它的原因,而不是你。
  • 这里有什么消息吗?解决了? :)
  • 不是真的,不是,但我认为我将问题缩小到飞机类。
  • 您是否设法获得线程虚拟机?如果是,请将其添加到您的问题中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2015-05-22
相关资源
最近更新 更多