- 假设你正在开发电梯的控制调度系统,请设计这个调度系统的控制逻辑,并能够响应以下场景:
-
- 客人在第n层按向上、向下的按钮
-
- 客人等待电梯到达
-
- 系统收到请求,按“就近”原则分配最快到达的电梯
-
- 客人进入电梯的时候能够指定目标楼层
-
- 在到达目标楼层途中可以响应其他同向的客人
-
- 不断轮询,有些已分配目标楼层的电梯在客人等待过程中还可以优化…
package bak;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Design {
public static void main(String[] args) {
Elevator elevator = new Elevator(null, 11, 1, 2);
new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
elevator.up(3);
}).start();
new Thread(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
elevator.up(5);
}).start();
new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
elevator.down(4);
}).start();
try {
elevator.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package bak;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Slf4j
public class Elevator {
private volatile Boolean isCurrentUp;
private final int maxFloor;
private final int minFloor;
private int currentFloor;
private final Map<Integer, Floor> floorMap = new HashMap<>();
private final Set<Integer> needDealFloorSet = new HashSet<>();
public Elevator(Boolean isCurrentUp, int maxFloor, int minFloor, int currentFloor) {
for(int floorNum = minFloor;floorNum <= maxFloor;floorNum++) {
floorMap.put(floorNum, new Floor(floorNum));
}
this.isCurrentUp = isCurrentUp;
this.maxFloor = maxFloor;
this.minFloor = minFloor;
this.currentFloor = currentFloor;
}
public void run() throws InterruptedException {
log.info("当前楼层号:" + currentFloor);
while(true) {
if(isCurrentUp == null || needDealFloorSet.size() == 0) {
continue;
}
if(isCurrentUp && topHas(currentFloor)) {
currentFloor++;
log.info("电梯向上了一层,当前楼层号:" + currentFloor);
} else if(!isCurrentUp && bottomHas(currentFloor)){
currentFloor--;
log.info("电梯向下了一层,当前楼层号:" + currentFloor);
}
Floor floor = floorMap.get(currentFloor);
if(floor.isIn()) {
floor.setIn(false);
log.info("用户进入,当前楼层号:" + currentFloor);
imitate();
}
if(floor.isOut()){
needDealFloorSet.remove(currentFloor);
floor.setOut(false);
log.info("用户走出,当前楼层号:" + currentFloor);
}
Thread.sleep(1000);
}
}
private void imitate() {
if(isCurrentUp && currentFloor == 3) {
new Thread(() -> toFloor(7)).start();
}
if(isCurrentUp && currentFloor == 5) {
new Thread(() -> toFloor(9)).start();
}
if(!isCurrentUp && currentFloor == 4) {
new Thread(() -> toFloor(1)).start();
}
}
public void up(int currentUserFloor) {
log.info("有用户点击向上,此时用户所在楼层号:" + currentUserFloor);
Floor floor = floorMap.get(currentUserFloor);
floor.setIn(true);
if((isCurrentUp == null || !isCurrentUp) && needDealFloorSet.size() == 0) {
isCurrentUp = true;
log.info("电梯开始向上");
}
needDealFloorSet.add(currentUserFloor);
}
public void down(int currentUserFloorNumber) {
log.info("有用户点击向下,此时用户所在楼层号:" + currentUserFloorNumber);
Floor floor = floorMap.get(currentUserFloorNumber);
floor.setIn(true);
if((isCurrentUp == null || isCurrentUp) || needDealFloorSet.size() == 0) {
isCurrentUp = false;
log.info("电梯开始向下");
}
needDealFloorSet.add(currentUserFloorNumber);
}
public void toFloor(int toFloorNumber) {
Floor floor = floorMap.get(toFloorNumber);
floor.setOut(true);
needDealFloorSet.add(toFloorNumber);
log.info("此时用户点击了想到达的楼层号:" + toFloorNumber);
}
private boolean topHas(int currentFloorNumber) {
for(int floorNumber = currentFloorNumber;floorNumber < maxFloor;floorNumber++) {
if(needDealFloorSet.contains(floorNumber)) {
return true;
}
}
return false;
}
private boolean bottomHas(int currentFloorNumber) {
for(int floorNumber = minFloor;floorNumber < currentFloorNumber;floorNumber++) {
if(needDealFloorSet.contains(floorNumber)) {
return true;
}
}
return false;
}
}
package bak;
import lombok.Data;
@Data
public class Floor {
private int number;
private boolean isIn = false;
private boolean isOut = false;
public Floor(int number) {
this.number = number;
}
}