第二次博客作业
uml图
流程控制
线程配合
主要线程 | 功能 |
---|---|
InputThread | 获取输入线程:获取输入的电梯请求和乘客请求,并分别存储到ElevatorRequestList与PersonRequestList中。 |
ElevatorAddThread | 电梯增加线程:提取ElevatorReuqestList中的电梯请求,并在系统中添加相应的电梯。 |
MainControlThread | 主控线程:提取PersonRequestList中的乘客请求,并生成对应的TaskChainThread线程(以下简称tct线程)来管理每一个请求对应的电梯运行。 |
TaskChainThreadPoolThread | 线程池线程:管理所有tct线程。在所有的tct线程执行完任务后,关闭所有电梯线程。 |
Main | 主线程:程序运行线程。 |
运行线程
线程类名称 | 功能 |
---|---|
VerticalElevator | 纵向电梯:负责处理接收到的纵向任务。 |
CircularElevator | 环形电梯:负责处理接收到的横向任务。 |
TaskChainThread | 任务链:存储任务链,并根据每一个任务的完成情况,将相应任务依次分配给相应电梯。 |
电梯分配策略
静态分配。
设计好两个类,分别是VerticalElevatorMap(以下简称VEM)与CircularElevatorMap(以下简称CEM),分别存储纵向电梯与横向电梯队列。MainControlThread(主控线程)将任务拆解为任务链,将其中的纵向任务分发送给VEM,获得已存在电梯中最优电梯;同理,获得CEM中的最优电梯。
初始化
private static void init() {
TimableOutput.initStartTimestamp();
ElevatorRequestList elevatorRequestList = new ElevatorRequestList();
PersonRequestList personRequestList = new PersonRequestList();
/*输入线程*/
new InputThread(personRequestList, elevatorRequestList).start();
VerticalElevatorMap verticalElevatorMap = new VerticalElevatorMap();
CircularElevatorMap circularElevatorMap = new CircularElevatorMap();
/*线程池线程*/
TaskChainThreadPoolThread tctpThread = new TaskChainThreadPoolThread(
verticalElevatorMap, circularElevatorMap);
tctpThread.start();
MainControlThread mainControlThread = new MainControlThread(
personRequestList, verticalElevatorMap, circularElevatorMap, tctpThread);
/*电梯主控线程*/
mainControlThread.start();
ElevatorAddThread elevatorAddThread = new ElevatorAddThread(
elevatorRequestList, verticalElevatorMap, circularElevatorMap);
/*电梯增加线程*/
elevatorAddThread.start();
/*初始电梯设置*/
VerticalElevatorTable verticalElevatorTableA = new VerticalElevatorTable(Building.A, 1, 8);
VerticalElevator verticalElevatorA = new VerticalElevator(
Building.A, 1, verticalElevatorTableA, 0.6);
verticalElevatorMap.add(verticalElevatorA);
new Thread(verticalElevatorA).start();
VerticalElevatorTable verticalElevatorTableB = new VerticalElevatorTable(Building.B, 2, 8);
VerticalElevator verticalElevatorB = new VerticalElevator(
Building.B, 2, verticalElevatorTableB, 0.6);
verticalElevatorMap.add(verticalElevatorB);
new Thread(verticalElevatorB).start();
VerticalElevatorTable verticalElevatorTableC = new VerticalElevatorTable(Building.C, 3, 8);
VerticalElevator verticalElevatorC = new VerticalElevator(
Building.C, 3, verticalElevatorTableC, 0.6);
verticalElevatorMap.add(verticalElevatorC);
new Thread(verticalElevatorC).start();
VerticalElevatorTable verticalElevatorTableD = new VerticalElevatorTable(Building.D, 4, 8);
VerticalElevator verticalElevatorD = new VerticalElevator(
Building.D, 4, verticalElevatorTableD, 0.6);
verticalElevatorMap.add(verticalElevatorD);
new Thread(verticalElevatorD).start();
VerticalElevatorTable verticalElevatorTableE = new VerticalElevatorTable(Building.E, 5, 8);
VerticalElevator verticalElevatorE = new VerticalElevator(
Building.E, 5, verticalElevatorTableE, 0.6);
verticalElevatorMap.add(verticalElevatorE);
new Thread(verticalElevatorE).start();
CircularElevatorTable circularElevatorTable = new CircularElevatorTable(1, 6, 8, 31);
CircularElevator circularElevator = new CircularElevator(1, 6, circularElevatorTable, 0.6);
circularElevatorMap.add(circularElevator);
new Thread(circularElevator).start();
}
代码分析
InputThread
分别将电梯请求与乘客请求放入elevatorRequestList与personRequestList中。注意设置相应list的setEnd()的方法。
private void work() {
ElevatorInput elevatorInput = new ElevatorInput(System.in);
while (true) {
Request request = elevatorInput.nextRequest();
if (null == request) {
personRequestList.setEnd();
elevatorRequestList.setEnd();
return;
} else {
if (request instanceof PersonRequest) {
personRequestList.add((PersonRequest) request);
} else if (request instanceof ElevatorRequest) {
elevatorRequestList.add((ElevatorRequest) request);
}
}
}
}
ElevatorRequestList, PersonRequestList
本质上是线程安全的List,将add()方法与take()方法注意上锁。其中take()方法如下:
public synchronized ElevatorRequest take() throws InterruptedException {
if (elevatorRequests.isEmpty()) {
wait();
}
if (elevatorRequests.isEmpty()) {
return null;
}
return this.elevatorRequests.take();
}
第一个isEmpty()代码块,由add()方法唤醒;第二个isEmpty()代码块,由setEnd()方法唤醒。
ElevatorTable
每一个Elevator都会分配一个自己的ElevatorTable,负责控制该电梯的状态。以VerticalElevatorTable为例。
将乘客需求拆分为TaskIn(进入电梯任务)与TaskOut(离开电梯任务),分别用两个队列存储,只有该乘客需求的TaskIn任务执行完之后,才能执行该乘客的TaskOut任务。若达到存储容量,则不能向ElevatorTable存放请求(wait()),直到某一个TaskOut任务执行完,表示一个乘客出电梯,则才可继续向ElevatorTable存放请求。
电梯每运行一层,都会判断ElevatorTable是否更新,然后指导该电梯下一步是向上还是向下。
每到达一个楼层,都会判断该楼层是否有相应的TaskIn和可执行的TaskOut任务,然后执行。
VerticalElevatorMap, CircularElevatorMap
VEM以座为键,存放该座所有的<VE, VET>;CEM以楼层为键,存放该楼层所有的<CE, CET>。最为核心的的方法是getProperElevatorTable()。
VEM的getProperElevatorTable(),本身策略很简单,即排着分配给该座的纵向电梯,即平均调度策略。通过一个循环迭代器来实现。
public synchronized VerticalElevatorTable getProperElevatorTable(
Building staticBuilding) throws Exception {
while (map.isEmpty()) {
wait();
}
Iterator<VerticalElevatorTable> iterator = iteratorMap.get(staticBuilding);
if (!iterator.hasNext()) {
iterator = map.get(staticBuilding).values().iterator();
iteratorMap.put(staticBuilding, iterator);
}
return iterator.next();
}
CEM的getProperElevatorTable()方法稍微复杂一下。才用只处理一次换乘,若满足
1. 小于等于1次换乘即可到达目标楼座。
1. 纵向上下楼层少于**前往一层**。
则才用该换乘策略,代码如下:
public synchronized CircularElevatorTable getProperElevatorTable(
Integer targetFloor, Building fromBuilding, Building toBuilding) throws Exception {
while (map.isEmpty()) {
wait();
}
List<CircularElevatorTable> list = new ArrayList<>();
for (Map<CircularElevator, CircularElevatorTable> cetMap : map.values()) {
for (CircularElevatorTable elevatorTable : cetMap.values()) {
if (elevatorTable.canReach(fromBuilding) && elevatorTable.canReach(toBuilding)) {
list.add(elevatorTable);
}
}
}
CircularElevatorTable chosenEt = null;
int distance = 100;
for (CircularElevatorTable elevatorTable : list) {
if (Math.abs(elevatorTable.getStaticFloor() - targetFloor) < distance) {
distance = Math.abs(elevatorTable.getStaticFloor() - targetFloor);
chosenEt = elevatorTable;
}
}
if (null == chosenEt) {
throw new Exception("Chosen Et is NULL!");
}
return chosenEt;
}
ElevatorAddThread
主要任务为两个:
1. start相应添加的电梯线程
1. 将相应的Elevator与ElevatorTable存储在VerticalElevatorList与CircularElevatorList中。
核心代码如下:
private void work() throws Exception {
while (true) {
if (elevatorRequestList.isEnd() && elevatorRequestList.isEmpty()) {
return;
}
ElevatorRequest request = elevatorRequestList.take();
if (null == request) {
continue;
}
int elevatorId = request.getElevatorId();
String type = request.getType();
Building building = Building.analyseChar(request.getBuilding());
int floor = request.getFloor();
int capacity = request.getCapacity();
double speed = request.getSpeed();
int switchInfo = request.getSwitchInfo();
if (type.equals("building")) {
VerticalElevator elevator = new VerticalElevator(building, elevatorId,
new VerticalElevatorTable(building, elevatorId, capacity), speed);
new Thread(elevator).start();
verticalElevatorMap.add(elevator);
} else {
CircularElevator elevator = new CircularElevator(floor, elevatorId,
new CircularElevatorTable(floor, elevatorId, capacity, switchInfo), speed);
new Thread(elevator).start();
circularElevatorMap.add(elevator);
}
}
}
MainControlThread
主要任务如下:
1. 提取乘客需求,并将需求拆解为**任务队列**。
1. 将每一个任务都分配给一个*适当*的电梯
1. 创建TaskChainThread(任务链线程,以下简称tct线程)来执行**任务队列**。
1. 将tct放入tctPool中。
核心方法为creatTaskChainThread(),代码如下:
private synchronized void createTaskChainThread(int id,
PersonRequest request) throws Exception {
int fromFloor = request.getFromFloor();
int toFloor = request.getToFloor();
Building fromBuilding = Building.analyseChar(request.getFromBuilding());
Building toBuilding = Building.analyseChar(request.getToBuilding());
int personId = request.getPersonId();
Queue<TaskNode> queue = new LinkedList<>();
if (fromBuilding.equals(toBuilding)) {
queue.add(new TaskNode(new VerticalRequest(personId, fromFloor, toFloor),
verticalElevatorMap.getProperElevatorTable(fromBuilding)));
} else {
int targetFloor = (fromFloor + toFloor) / 2; //在精度上问题不大
int transferFloor = circularElevatorMap.getProperElevatorFloor(
targetFloor, fromBuilding, toBuilding);
if (fromFloor != transferFloor) {
queue.add(new TaskNode(new VerticalRequest(personId, fromFloor, transferFloor),
verticalElevatorMap.getProperElevatorTable(fromBuilding)));
}
queue.add(new TaskNode(new CircularRequest(personId, fromBuilding, toBuilding),
circularElevatorMap.getProperElevatorTable(
targetFloor, fromBuilding, toBuilding)));
if (transferFloor != toFloor) {
queue.add(new TaskNode(new VerticalRequest(personId, transferFloor, toFloor),
verticalElevatorMap.getProperElevatorTable(toBuilding)));
}
}
TaskChainThread taskChainThread = new TaskChainThread(id, queue, tctpThread);
tctpThread.add(taskChainThread);
taskChainThread.start();
}
TaskChainPoolThread
主要任务负责管理整个程序结束:在所有tct线程结束前,所有电梯都保持运行。
程序缺点分析
最根本的问题,来自于只能静态分配电梯,而不能实时将请求分配给新加入的电梯。
导致强测很多测试点,RTLE,就是有的电梯很忙,有的电梯空闲。
后期,可以加入任务回溯模块。每个电梯任务在执行之前,在重新考虑一下是否分配合理。
度量分析
Method metrics
method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
com.company.VerticalRequest.VerticalRequest(int, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalRequest.getId() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalRequest.addToElevatorTable(ElevatorTable) | 2.0 | 2.0 | 2.0 | 2.0 |
com.company.VerticalElevatorTable.VerticalElevatorTable(Building, Integer, Integer) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorTable.setEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorTable.isEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorTable.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorTable.hasNoCapacity() | 2.0 | 2.0 | 1.0 | 3.0 |
com.company.VerticalElevatorTable.getTask(int) | 4.0 | 3.0 | 3.0 | 4.0 |
com.company.VerticalElevatorTable.finishTask(int) | 7.0 | 2.0 | 4.0 | 4.0 |
com.company.VerticalElevatorTable.changeExecutable(int) | 7.0 | 1.0 | 4.0 | 4.0 |
com.company.VerticalElevatorTable.binarySearch(int) | 13.0 | 7.0 | 6.0 | 11.0 |
com.company.VerticalElevatorTable.addTask(TaskNode) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorTable.addTask(int, int, TaskOut) | 2.0 | 1.0 | 2.0 | 2.0 |
com.company.VerticalElevatorTable.addTask(int, int, TaskIn) | 3.0 | 1.0 | 3.0 | 3.0 |
com.company.VerticalElevatorMap.setAllElevatorTableEnd() | 3.0 | 1.0 | 3.0 | 3.0 |
com.company.VerticalElevatorMap.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevatorMap.getProperElevatorTable(Building) | 2.0 | 1.0 | 3.0 | 3.0 |
com.company.VerticalElevatorMap.add(VerticalElevator) | 2.0 | 1.0 | 2.0 | 2.0 |
com.company.VerticalElevator.work() | 11.0 | 4.0 | 5.0 | 7.0 |
com.company.VerticalElevator.VerticalElevator(Building, int, VerticalElevatorTable, double) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.VerticalElevator.open() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.move(int) | 2.0 | 1.0 | 1.0 | 2.0 |
com.company.VerticalElevator.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.getVerticalElevatorTable() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.getStaticBuilding() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.getId() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.executeTask() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.equals(Object) | 2.0 | 3.0 | 1.0 | 3.0 |
com.company.VerticalElevator.close() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.VerticalElevator.arrive() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskOut.executeTask(int, Building, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskNode.TaskNode(ExecutableRequest, ElevatorTable) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskNode.setFinished() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskNode.isFinished() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.TaskNode.getId() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskNode.getElevatorTable() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskNode.addTaskToElevatorTable() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskIn.executeTask(int, Building, int, int) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.work() | 5.0 | 3.0 | 4.0 | 4.0 |
com.company.TaskChainThreadPoolThread.TaskChainThreadPoolThread(VerticalElevatorMap, CircularElevatorMap) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.setEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.setAllElevatorTableEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.TaskChainThreadPoolThread.isEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThreadPoolThread.finish(TaskChainThread) | 1.0 | 2.0 | 1.0 | 2.0 |
com.company.TaskChainThreadPoolThread.add(TaskChainThread) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThread.work() | 7.0 | 4.0 | 4.0 | 4.0 |
com.company.TaskChainThread.TaskChainThread(int, Queue, TaskChainThreadPoolThread) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.TaskChainThread.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.TaskChainThread.equals(Object) | 1.0 | 1.0 | 1.0 | 2.0 |
com.company.TaskChainThread.addTask(TaskNode) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.PersonRequestList.take() | 2.0 | 2.0 | 2.0 | 3.0 |
com.company.PersonRequestList.setEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.PersonRequestList.isEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.PersonRequestList.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.PersonRequestList.add(PersonRequest) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.OutputClass.println(String) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.MainControlThread.work() | 6.0 | 4.0 | 4.0 | 5.0 |
com.company.MainControlThread.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.MainControlThread.MainControlThread(PersonRequestList, VerticalElevatorMap, CircularElevatorMap, TaskChainThreadPoolThread) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.MainControlThread.createTaskChainThread(int, PersonRequest) | 6.0 | 1.0 | 4.0 | 4.0 |
com.company.Main.main(String[]) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.Main.init() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.InputThread.work() | 8.0 | 3.0 | 5.0 | 5.0 |
com.company.InputThread.run() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.InputThread.InputThread(PersonRequestList, ElevatorRequestList) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.ElevatorRequestList.take() | 2.0 | 2.0 | 2.0 | 3.0 |
com.company.ElevatorRequestList.setEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.ElevatorRequestList.isEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.ElevatorRequestList.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.ElevatorRequestList.add(ElevatorRequest) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.ElevatorAddThread.work() | 9.0 | 4.0 | 4.0 | 6.0 |
com.company.ElevatorAddThread.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.ElevatorAddThread.ElevatorAddThread(ElevatorRequestList, VerticalElevatorMap, CircularElevatorMap) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularRequest.getId() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularRequest.CircularRequest(int, Building, Building) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularRequest.addToElevatorTable(ElevatorTable) | 2.0 | 2.0 | 2.0 | 2.0 |
com.company.CircularElevatorTable.setEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.nearestSearch(Building) | 31.0 | 26.0 | 21.0 | 26.0 |
com.company.CircularElevatorTable.isEnd() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.hasNoCapacity() | 2.0 | 2.0 | 1.0 | 3.0 |
com.company.CircularElevatorTable.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.getTask(Building) | 4.0 | 3.0 | 3.0 | 4.0 |
com.company.CircularElevatorTable.getStaticFloor() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.finishTask(Building) | 7.0 | 2.0 | 4.0 | 4.0 |
com.company.CircularElevatorTable.equals(Object) | 2.0 | 3.0 | 1.0 | 3.0 |
com.company.CircularElevatorTable.CircularElevatorTable(Integer, Integer, Integer, Integer) | 3.0 | 1.0 | 3.0 | 3.0 |
com.company.CircularElevatorTable.changeExecutable(int) | 7.0 | 1.0 | 4.0 | 4.0 |
com.company.CircularElevatorTable.canReach(Building) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.addTask(TaskNode) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorTable.addTask(int, Building, TaskOut) | 2.0 | 1.0 | 2.0 | 2.0 |
com.company.CircularElevatorTable.addTask(int, Building, TaskIn) | 3.0 | 1.0 | 3.0 | 3.0 |
com.company.CircularElevatorMap.setAllElevatorTableEnd() | 3.0 | 1.0 | 3.0 | 3.0 |
com.company.CircularElevatorMap.isEmpty() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorMap.getProperElevatorTable(Integer, Building, Building) | 12.0 | 2.0 | 8.0 | 9.0 |
com.company.CircularElevatorMap.getProperElevatorFloor(Integer, Building, Building) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevatorMap.add(CircularElevator) | 2.0 | 1.0 | 2.0 | 2.0 |
com.company.CircularElevator.work() | 11.0 | 4.0 | 5.0 | 7.0 |
com.company.CircularElevator.run() | 1.0 | 1.0 | 2.0 | 2.0 |
com.company.CircularElevator.open() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.move(Building) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.hashCode() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.getStaticFloor() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.getId() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.getCircularElevatorTable() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.executeTask() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.equals(Object) | 2.0 | 3.0 | 1.0 | 3.0 |
com.company.CircularElevator.close() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.CircularElevator(Integer, int, CircularElevatorTable, double) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.CircularElevator.arrive() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.Building.getValue() | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.Building.getNextBuilding(Building, Building) | 11.0 | 21.0 | 1.0 | 21.0 |
com.company.Building.Building(int) | 0.0 | 1.0 | 1.0 | 1.0 |
com.company.Building.analyseChar(char) | 1.0 | 6.0 | 1.0 | 6.0 |
Total | 221.0 | 213.0 | 220.0 | 280.0 |
Average | 1.8728813559322033 | 1.805084745762712 | 1.8644067796610169 | 2.3728813559322033 |
总的来说,涉及到环形电梯运行的方法,就会复杂度很高。比如说:CircularElevatorTable的nearestSearch()方法
private Building nearestSearch(Building currentBuilding) throws Exception {
switch (currentBuilding) {
case A: { if (executableMap.containsKey(Building.B)) {
return Building.B;
} else if (executableMap.containsKey(Building.E)) {
return Building.E;
} else if (executableMap.containsKey(Building.C)) {
return Building.C;
} else if (executableMap.containsKey(Building.D)) {
return Building.D;
} else {
throw new Exception("This Building DOESN'T Exist!");
}
} case B: { if (executableMap.containsKey(Building.C)) {
return Building.C;
} else if (executableMap.containsKey(Building.A)) {
return Building.A;
} else if (executableMap.containsKey(Building.D)) {
return Building.D;
} else if (executableMap.containsKey(Building.E)) {
return Building.E;
} else {
throw new Exception("This Building DOESN'T Exist!");
}
} case C: { if (executableMap.containsKey(Building.D)) {
return Building.D;
} else if (executableMap.containsKey(Building.B)) {
return Building.B;
} else if (executableMap.containsKey(Building.E)) {
return Building.E;
} else if (executableMap.containsKey(Building.A)) {
return Building.A;
} else {
throw new Exception("This Building DOESN'T Exist!");
}
} case D: { if (executableMap.containsKey(Building.E)) {
return Building.E;
} else if (executableMap.containsKey(Building.C)) {
return Building.C;
} else if (executableMap.containsKey(Building.A)) {
return Building.A;
} else if (executableMap.containsKey(Building.B)) {
return Building.B;
} else {
throw new Exception("This Building DOESN'T Exist!");
}
} case E: { if (executableMap.containsKey(Building.A)) {
return Building.A;
} else if (executableMap.containsKey(Building.D)) {
return Building.D;
} else if (executableMap.containsKey(Building.B)) {
return Building.B;
} else if (executableMap.containsKey(Building.C)) {
return Building.C;
} else {
throw new Exception("This Building DOESN'T Exist!");
}
} default:
} throw new Exception("Exceptions with Building Select!");
}
通过暴力枚举五个楼座之间的关系,从而确保最短路径选择,导致了很难看的复杂度情况。