Получив в голову потоки Java, мониторы и т.д .... - PullRequest
0 голосов
/ 06 марта 2012

Я работаю над проектом, в котором мне нужно рисовать круговые очереди и резьбы, чтобы имитировать, как поезд поднимает и опускает пассажиров.Я использую Object.notify и Object.wait для управления потоками.Я новичок в приложениях Threading и получаю эту ошибку, которую не понимаю:

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(); 
        }
    }

Вот мой класс Train, который будет двигаться дальшедорожка до каждой станции, с которой отправляются пассажиры:

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;
    }
}

Вот класс моей станции, где он генерирует пассажиров, которые едут в поезде, пока он ждет поезда, чтобы сесть на станцию:

import java.util.Random;

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);
        }
    }
}

Как видно, контроль выполнения программных потоков между поездом и объектами станции осуществляется с помощью .wait ();и .notify () ;.У меня такое ощущение, что есть намного более элегантный способ обработки потоков ... Почему .notify () имеет на нем монитор?Есть ли лучший способ обработки потоков в моем случае?Извините, если это глупые вопросы.

Ответы [ 3 ]

2 голосов
/ 06 марта 2012
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().

1 голос
/ 06 марта 2012

Вы не можете вызвать notify или wait для объекта, не получив сначала блокировку объекта.

В Station.java вы вызываете trainStation.notify () в вашем методе run (), но блокируетекода не синхронизируется с trainStation.

синхронизируйте блоки кода, которые вызывают ожидание или уведомляют, против объекта, который вы вызываете, ожидают или уведомляют, и ваши непосредственные проблемы должны исчезнуть.

1 голос
/ 06 марта 2012

Вам нужно добавить синхронизированный блок вокруг ваших вызовов wait ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...