2012-03-06 1 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(); 

:基本的にどこでもあなたがnotify()notifyAll()を呼び出す

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

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

または多分これらの1 。

1

wait()呼び出しの前後に同期ブロックを追加する必要があります。

1

オブジェクトに対してロックを最初に取得することなく、notifyまたはwaitを呼び出すことはできません。

Station.javaでは、run()メソッドでtrainStation.notify()を呼び出していますが、コードブロックはtrainStationと同期していません。

あなたが呼び出しているオブジェクトに対して待機または通知する呼び出しブロックを同期させて、待機または通知してください。すぐに問題が解決するはずです。

関連する問題