我正在开展一个项目,我需要进行圆形和螺纹加工来模拟火车接送乘客。我使用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();
}
}
这是我的火车课程,它将沿着轨道移动到每个站点下车并接载乘客:
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()有一个监视器?在我的情况下,有更好的方法来处理线程吗?对不起,如果这些都是愚蠢的问题。
答案 0 :(得分: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)
这是试图告诉您正在调用对象上的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 :(得分:1)
您需要在wait()调用周围添加一个synchronized块。
答案 2 :(得分:1)
如果没有先获取对象的锁定,则无法调用通知或等待对象。
在Station.java中,您在run()方法中调用trainStation.notify(),但代码块未与trainStation同步。
将调用wait或notify的代码块与您正在调用的对象进行同步或通知,并立即解决您的问题。