我正在编写一个电梯模拟器,它在一个单独的线程中运行每个电梯。每部电梯都有自己的目的地列表。在我的主要方法中,我叫2号电梯搬到14层。当它行驶到14时,我告诉它在13停下来(它在14之前停下来)。当它移动到13和14时,我也告诉它移动到15。然而,我发现我的主要方法在请求14层之后停止,等待电梯到达14层,然后最终执行对15层的请求。
它为什么要这么做?我想不通。
这是我的输出:
00:00:00:000 Creating building...
00:00:00:012 Building created - 16 floors, 4 elevators
00:00:00:014 Elevator 1 going to Floor 11 for UP request [Floor Requests: 11, ][Rider Requests:]
00:00:00:015 Elevator 1 moving from Floor 1 to Floor 2 [Floor Requests: 11, ][Rider Requests:]
00:00:00:520 Elevator 1 moving from Floor 2 to Floor 3 [Floor Requests: 11, ][Rider Requests:]
00:00:01:018 Elevator 2 going to Floor 14 for UP request [Floor Requests: 14, ][Rider Requests:]
00:00:01:020 Elevator 2 moving from Floor 1 to Floor 2 [Floor Requests: 14, ][Rider Requests:]
00:00:01:021 Elevator 1 moving from Floor 3 to Floor 4 [Floor Requests: 11, ][Rider Requests:]
00:00:01:521 Elevator 2 going to Floor 13 for UP request [Floor Requests: 13, 14, ][Rider Requests:]
00:00:01:523 Elevator 1 moving from Floor 4 to Floor 5 [Floor Requests: 11, ][Rider Requests:]
00:00:01:523 Elevator 2 moving from Floor 2 to Floor 3 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:02:025 Elevator 1 moving from Floor 5 to Floor 6 [Floor Requests: 11, ][Rider Requests:]
00:00:02:026 Elevator 2 moving from Floor 3 to Floor 4 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:02:529 Elevator 1 moving from Floor 6 to Floor 7 [Floor Requests: 11, ][Rider Requests:]
00:00:02:530 Elevator 2 moving from Floor 4 to Floor 5 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:03:032 Elevator 1 moving from Floor 7 to Floor 8 [Floor Requests: 11, ][Rider Requests:]
00:00:03:032 Elevator 2 moving from Floor 5 to Floor 6 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:03:537 Elevator 1 moving from Floor 8 to Floor 9 [Floor Requests: 11, ][Rider Requests:]
00:00:03:539 Elevator 2 moving from Floor 6 to Floor 7 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:04:040 Elevator 1 moving from Floor 9 to Floor 10 [Floor Requests: 11, ][Rider Requests:]
00:00:04:042 Elevator 2 moving from Floor 7 to Floor 8 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:04:542 Elevator 1 moving from Floor 10 to Floor 11 [Floor Requests: 11, ][Rider Requests:]
00:00:04:544 Elevator 2 moving from Floor 8 to Floor 9 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:05:047 Elevator 2 moving from Floor 9 to Floor 10 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:05:047 Elevator 1 Doors Open
00:00:05:551 Elevator 1 Doors Close
00:00:05:550 Elevator 2 moving from Floor 10 to Floor 11 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:06:054 Elevator 2 moving from Floor 11 to Floor 12 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:06:556 Elevator 2 moving from Floor 12 to Floor 13 [Floor Requests: 13, 14, ][Rider Requests:]
00:00:07:062 Elevator 2 Doors Open
00:00:07:566 Elevator 2 Doors Close
00:00:07:567 Elevator 2 moving from Floor 13 to Floor 14 [Floor Requests: 14, ][Rider Requests:]
00:00:08:069 Elevator 2 Doors Open
00:00:08:570 Elevator 2 Doors Close
00:00:08:571 Let's see when this is being called00:00:08:572 Elevator 2 going to Floor 15 for UP request [Floor Requests: 15, ][Rider Requests:]
00:00:08:572 Elevator 2 moving from Floor 14 to Floor 15 [Floor Requests: 15, ][Rider Requests:]
00:00:09:076 Elevator 2 Doors Open
00:00:09:582 Elevator 2 Doors Close
主要方法:
公共类ElevatorSimulatorMain{
private static long startTime = System.currentTimeMillis();
public static void main(String[] args) {
// make a building with elevators
System.out.println(getTimeStamp() + "Creating building...");
Building testBuilding = new Building(16, 4); //16 floors and 4 elevators
System.out.printf(getTimeStamp()
+ "Building created - %d floors, %d elevatorsn",
testBuilding.getNumFloors(), testBuilding.getNumElevators());
// create a thread for each elevator
for (int i = 1; i <= testBuilding.getNumElevators(); i++) {
Thread t = new Thread(testBuilding.getPassengerElevatorbyID(i));
t.start();
}
// Elevator 1 to floor 11
try {
testBuilding.getController().sendElevator(11, 1);
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ElevatorSimulatorMain.class.getName()).log(Level.SEVERE, null, ex);
}
// Elevator 2 to floor 14
try {
testBuilding.getController().sendElevator(14, 2);
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(ElevatorSimulatorMain.class.getName()).log(Level.SEVERE, null, ex);
}
// Elevator 2 to floor 13 while still in transit to floor 14
try {
testBuilding.getController().sendElevator(13, 2);
} catch (InterruptedException ex) {
Logger.getLogger(ElevatorSimulatorMain.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.printf(ElevatorSimulatorMain.getTimeStamp() + "Let's see when this is being called");
// Elevator 2 to floor 15 while still in transit to floor 13
try {
testBuilding.getController().sendElevator(15, 2);
} catch (InterruptedException ex) {
Logger.getLogger(ElevatorSimulatorMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
乘客电梯线程
公共乘客电梯(int-elevID){
this.elevID = elevID;
travelSpeed = 500; // in milliseconds
doorSpeed = 500; // in milliseconds
currentFloor = 1;
defaultFloor = 1;
currentState = Direction.IDLE;
tempDestinations = new ArrayList<>();
upDestinations = new ArrayList<>();
downDestinations = new ArrayList<>();
}
@Override
public void run() {
boolean running = true; // flag for keeping the thread running
while (running) {
try {
synchronized (tempDestinations) {
if (upDestinations.isEmpty() && downDestinations.isEmpty()){
tempDestinations.wait();
if (!downDestinations.isEmpty()) {
processDownRequest();
}
else if (!upDestinations.isEmpty()) {
processUpRequest();
}
}
}
}
catch (InterruptedException ex) {
System.out.println("Interrupted! Going back to check for " +
"requests/wait");
}
}
}
/**
* Make elevator go up one floor. Takes travelSpeed time
* @throws InterruptedException
*/
@Override
public void moveUp() throws InterruptedException {
setCurrentFloor(currentFloor++);
Thread.sleep(travelSpeed);
}
/**
* Make elevator go down one floor. Takes travelSpeed time
* @throws InterruptedException
*/
@Override
public void moveDown() throws InterruptedException{
setCurrentFloor(currentFloor--);
Thread.sleep(travelSpeed);
}
/**
* Make elevator door open for doorSpeed time. When door is open people
* move into elevator
* @throws InterruptedException
*/
@Override
public void openDoors() throws InterruptedException{
System.out.printf(ElevatorSimulatorMain.getTimeStamp() + "Elevator %d "
+ "Doors Openn", elevID);
Thread.sleep(doorSpeed);
System.out.printf(ElevatorSimulatorMain.getTimeStamp() + "Elevator %d "
+ "Doors Closen", elevID);
}
/**
* Moves the elevator up to the first destination in upDestinations.
* When it gets there, it removes the destination from upDestinations.
* @throws InterruptedException
*/
private void processUpRequest() throws InterruptedException {
while (!upDestinations.isEmpty()) {
if (currentFloor != upDestinations.get(0)) {
currentState = Direction.UP;
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d moving from Floor %d to Floor %d "
+ "[Floor Requests: %s][Rider Requests:]n", elevID,
currentFloor, ++currentFloor,
printRequests(upDestinations));
moveUp();
}
else {
upDestinations.remove(0);
openDoors();
}
}
currentState = Direction.IDLE;
}
/**
* Moves the elevator down to the first destination in downDestinations.
* When it gets there, it removes the destination from downDestinations.
* @throws InterruptedException
*/
private void processDownRequest() throws InterruptedException {
while (!downDestinations.isEmpty()) {
if (currentFloor != downDestinations.get(0)) {
currentState = Direction.DOWN;
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d moving from Floor %d to Floor %d "
+ "[Floor Requests: %s][Rider Requests:]n", elevID,
currentFloor, --currentFloor,
printRequests(downDestinations));
moveDown();
}
else {
downDestinations.remove(0);
openDoors();
}
}
currentState = Direction.IDLE;
}
/**
* add a destination for the elevator to stop at
* @param floor for the elevator to travel to
*/
public void addDestination(int floor) {
// if elevator is moving down
if (!downDestinations.isEmpty() && currentState == Direction.DOWN) {
addDestinationWhenMovingDown(floor);
}
// if elevator is moving UP
else if (!upDestinations.isEmpty() && currentState == Direction.UP) {
addDestinationWhenMovingUp(floor);
}
// if elevator is IDLE
else {
addDestinationWhenIdle(floor);
}
/*
this is just an object to conveniently call on to indicate there must
have been a destination added since you cannot call wait on
upDestinations and downDestinations at the same time.
*/
synchronized (tempDestinations) {
tempDestinations.notifyAll();
}
}
/**
* Handle adding a destination when the elevator state is idle.
* @param floor - the floor the request was made on
*/
private void addDestinationWhenIdle(int floor) {
// request to go UP
if (floor > currentFloor) {
upDestinations.add(floor);
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d going to Floor %d for UP request"
+ " [Floor Requests: %s][Rider Requests:]n",elevID,
upDestinations.get(0),
printRequests(upDestinations));
}
// request to go DOWN
else if (floor < currentFloor) {
downDestinations.add(floor);
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d going to Floor %d for DOWN request"
+ " [Floor Requests: %s][Rider Requests:]n",elevID,
downDestinations.get(0),
printRequests(downDestinations));
}
// already on that floor, do nothing
else {}
}
/**
* Handle adding a destination when the elevator is moving up. Checks to see
* if request is in the destination list already. If it isn't, it adds it to
* the list and sorts the list in order of when the elevator should go first
* @param floor - the floor the request was made on
*/
private void addDestinationWhenMovingUp(int floor) {
// if it isn't already in the list, add it and sort it.
// do nothing if it is already in the list
if (!upDestinations.contains(floor)) {
upDestinations.add(floor);
Collections.sort(upDestinations);
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d going to Floor %d for UP request"
+ " [Floor Requests: %s][Rider Requests:]n",elevID,
upDestinations.get(0),
printRequests(upDestinations));
}
}
/**
* Handle adding a destination when the elevator is moving down. Checks to
* see if request is in the destination list already. If it isn't, it adds
* it to the list and sorts the list in order of when the elevator should go
* first.
* @param floor - the floor the request was made on
*/
private void addDestinationWhenMovingDown(int floor) {
// if it isn't already in the list, add it and sort it.
// do nothing if it is already in the list
if (!downDestinations.contains(floor)) {
downDestinations.add(floor);
Collections.sort(upDestinations);
Collections.reverse(upDestinations);
System.out.printf(ElevatorSimulatorMain.getTimeStamp()
+ "Elevator %d going to Floor %d for DOWN request"
+ " [Floor Requests: %s][Rider Requests:]n",elevID,
downDestinations.get(0),
printRequests(downDestinations));
}
}
解决:当电梯移动方法试图执行时,锁定的tempDestinationsList持有锁。我将锁更改为释放,然后调用了处理请求的方法。
以下是固定的代码片段:@Override public void run(){
boolean running = true; // flag for keeping the thread running
while (running) {
try {
synchronized (tempDestinations) {
if (upDestinations.isEmpty() && downDestinations.isEmpty()){
tempDestinations.wait();
}
}
if (!downDestinations.isEmpty()) {
processDownRequest();
}
else if (!upDestinations.isEmpty()) {
processUpRequest();
}
}
catch (InterruptedException ex) {
System.out.println("Interrupted! Going back to check for " +
"requests/wait");
}
}