2012-03-06 43 views
0

我正在开发一个项目,我需要使用循环线程和线程来模拟火车接送乘客。我使用Object.notify和Object.wait来控制线程。我是新线程的应用程序,我得到这个错误,我不明白:让我的头绕过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; 
    } 
} 

这是我站类的地方产生的乘客去的火车上,而等待火车登上站:

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()有一个监视器呢?在我的情况下是否有更好的方法来处理线程?对不起,如果这些都是愚蠢的问题。

回答

2
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) 

这是想告诉你,你正在拨打的对象上不通知是一个​​块为对象内。这可能是在这里:

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

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

1

没有首先获取对象上的锁定,您无法调用notify或wait对象。

在Station.java中,您在run()方法中调用了trainStation.notify(),但代码块并未与trainStation同步。

同步调用等待或通知的代码块与您正在呼叫的对象等待或通知,您的直接问题应该消失。