有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程让我的头围绕Java线程,监视器等。。。。

我正在做一个项目,我需要循环排队和穿线来模拟火车上下乘客。我正在使用对象。通知并反对。等待以控制线程。我是线程应用程序的新手,我遇到了一个我不理解的错误:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at Station.run(Station.java:37)
    at java.lang.Thread.run(Unknown Source)

这是我的主要任务

public static void main(String[] args) 
    {
        Track theTrack = new Track();
        Station[] stations = {new Station(TRAIN_STATION_TYPE.ASHMONT)};
        Train[] trains = {new Train(TRAIN_TYPE.A_TRAIN, theTrack)};  

        Thread[] stationThreads = new Thread[stations.length]; 
        Thread[] trainThreads = new Thread[trains.length]; 

        theTrack.setStations(stations);
        theTrack.setTrains(trains); 
        for(int i = 0; i<stations.length; i++)
        {
            stationThreads[i] = new Thread(stations[i]);
            stationThreads[i].start(); 
        }
        for(int i = 0; i<trains.length; i++)
        {
            trainThreads[i] = new Thread(trains[i]);
            trainThreads[i].start(); 
        }
    }

这是我的火车班,它将沿着轨道移动到每个车站上下乘客:

public class Train implements Runnable
{
    TRAIN_TYPE trainType; 
    int location; 
    private boolean goingForward, trainIsRunning; 
    private Track track; 
    private CircularQueue <Passenger> passengers;
    private Station stationBoarded; 
    Train()
    {
        this(null);
    }
    Train(TRAIN_TYPE trainType)
    {
        this(trainType, null); 
    }
    Train(TRAIN_TYPE trainType, Track track)
    {
        this.trainType = trainType;
        location = trainType.location(); 
        this.track = track; 
        trainIsRunning = true;
        goingForward = true; 
    }
    @Override
    public void run() 
    {
        while(trainIsRunning)
        {
            moveTrain();// train is moving up or down the track until it hits the location of a station 
            setStationBoarded(track.arriveAtStation(location)); // board station
            stationBoarded.queueTrain(this);// queue this train
            justWait(); // wait to be notified
            unloadPassengers();// unload passengers
            stationBoarded.notify();//notify station boarded to allow passengers to board the train. 
            justWait(); // wait to be notified to leave
            depart(); 
        }
    }
    public boolean boardTrain(Passenger p)
    {
        if(!passengers.reachedCapacity())
        {
            passengers.enqueue(p);
            return true; 
        }
            return false; 
    }
    public void moveTrain()
    {
        while(track.arriveAtStation(location) == null)
        {
            TIME_CONSTANT.TRAIN_MOVE_TIME.sleepAWhile();
            if(goingForward)
                location++;
            else
                location--;
            if(!track.isOnTrack(location))
                goingForward = !goingForward;
        }
    }
    public void unloadPassengers()
    {
        for(int i = 0; i<passengers.getLength(); i++)
        {
            if(passengers.peekAtIndex(i).getDestination() == stationBoarded.getTrainStation())
                stationBoarded.queuePassenger(passengers.remove(passengers.peekAtIndex(i)));
        }
    }
    public synchronized void justWait()
    {
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }
    public void depart()
    {
        this.stationBoarded = null; 
    }
    public synchronized Passenger leaveTrain()
    {
        return passengers.dequeue(); 
    }
    public boolean isTrainIsRunning() {
        return trainIsRunning;
    }
    public void setTrainIsRunning(boolean trainIsRunning) {
        this.trainIsRunning = trainIsRunning;
    }
    public int getLocation() {
        return location;
    }
    public void setLocation(int location) {
        this.location = location;
    }
    public int getCapacity() 
    {
        return this.trainType.capacity();
    }
    public Station getStationBoarded() 
    {
        return stationBoarded;
    }
    public void setStationBoarded(Station stationBoarded) {
        this.stationBoarded = stationBoarded;
    }
    public boolean trainIsEmpty()
    {
        return this.passengers.isEmpty();
    }
    public boolean trainHasReachedCapacity()
    {
        return passengers.reachedCapacity();
    }
    public Track getTrack() {
        return track;
    }
    public void setTrack(Track track) {
        this.track = track;
    }
}

这是我的station类,它在等待火车进站时生成乘客上车:

导入java。util。随机的

public class Station implements Runnable  
{
    CircularQueue <Passenger> passengers;
    CircularQueue <Train> trains; 
    TRAIN_STATION_TYPE trainStation; 
    Train trainInStation;
    int location, numOfPassengers;
    Passenger tempPassenger; 
    Random ran = new Random(); 
    Station()
    {
        this (null);
    }
    Station(TRAIN_STATION_TYPE tranStation)
    {
        this(tranStation, null);
    }
    Station(TRAIN_STATION_TYPE trainStation, Train train)
    {
        this.trainStation = trainStation;
        this.trainInStation = train; 
        this.trains = new CircularQueue(); 
        this.passengers = new CircularQueue();
    }
    public void run() 
    {
        while(trains.isEmpty())
        {
            genPassengers();
        }
        while(!trains.isEmpty())
        {
            trainInStation = trains.dequeue();
            trainInStation.notify(); // notify the train to let the passengers off
            justWait();  // wait for train to unload passengers 
            unloadPassengers(); 
            trainInStation.notify();//notify the train to depart
            departTrain(); 
        }
    }
    public void genPassengers()
    {
        TIME_CONSTANT.PASSENGER_GEN_TIME.sleepAWhile();
        passengers.enqueue(new Passenger()); 
    }
    public void departTrain()
    {
        trainInStation = null; 
    }
    public void arrive(Train train)
    {
        this.trainInStation = train;
    }
    public Train depart()
    {
        Train tempTrain = this.trainInStation;
        this.trainInStation = null;
        return tempTrain; 
    }
    public int getLocation() {
        return location;
    }
    public void setLocation(int location) {
        this.location = location;
    }
    public boolean isBoarded()
    {
        return (trainInStation != null);
    }
    public Train getTrain() {
        return trainInStation;
    }
    public void setTrain(Train train) {
        this.trainInStation = train;
    }
    public synchronized void queueTrain(Train train) {
        trains.enqueue(train);
    }
    public synchronized Train dequeue() {
        return trains.dequeue(); 
    }
    public synchronized void queuePassenger(Passenger passenger){
        passengers.enqueue(passenger);
    }
    public synchronized Passenger dequeuePassenger()
    {
        return passengers.dequeue(); 
    }
    public TRAIN_STATION_TYPE getTrainStation() {
        return trainStation;
    }
    public void setTrainStation(TRAIN_STATION_TYPE trainStation) {
        this.trainStation = trainStation;
    }
    public void justWait()
    {
        try {
            this.wait(); //wait for passengers to get off
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void unloadPassengers()
    {
//      for(int i = 0; i<passengers.getLength() && !trainInStation.trainHasReachedCapacity(); i++)
//      {
//          trainInStation.boardTrain(passengers.dequeue());
//      }
        while(!passengers.isEmpty() && trainInStation.getCapacity()>numOfPassengers)
        {
            Passenger temp = dequeuePassenger(); 
            System.out.println(temp.toString() + " got on train " + this.trainInStation.trainType.getName()); 
            trainInStation.boardTrain(temp);
        }
    }
}

正如您所看到的,通过使用,可以控制列车和车站对象之间的程序流的执行。等待();和通知();。我有一种感觉,有一种更优雅的方式来处理线程。。。为什么呢。notify()上有监视器吗?在我的情况下,有没有更好的方法来处理线程?如果这些是愚蠢的问题,对不起


共 (3) 个答案

  1. # 1 楼答案

    如果不先获取对象的锁,就不能调用notify或等待对象

    在车站。爪哇,你在给火车站打电话。在run()方法中使用notify(),但代码块不会与trainStation同步

    将调用wait或notify的代码块与正在调用wait或notify的对象同步,立即出现的问题就会消失

  2. # 2 楼答案

    您需要在wait()调用周围添加一个同步块

  3. # 3 楼答案

    Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
       at java.lang.Object.notify(Native Method)
       at Station.run(Station.java:37)
       at java.lang.Thread.run(Unknown Source)
    

    这试图告诉您,您正在对一个对象调用notify,而不在该对象的synchronized块内。它可能在这里:

    stationBoarded.notify();
    

    您需要将其与以下内容同步:

    synchronized (stationBoarded) {
        stationBoarded.notify();
    }
    

    或者是其中之一:

    trainInStation.notify(); // notify the train to let the passengers off
    ...
    trainInStation.notify();//notify the train to depart
    

    基本上是你称之为notify()notifyAll()的任何地方