2012-03-06 40 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同步。

同步調用等待或通知的代碼塊與您正在呼叫的對象等待或通知,您的直接問題應該消失。