BUAA_2022_OO_第二单元总结
作者:互联网
2022_OO_Unit2
本单元作业为电梯调度,作业背景为存在A、B、C、D、E五栋楼,每栋楼10层。乘客乘坐电梯时需要告知其目的地。
作业1:每栋楼各一个电梯,可达1-10层,速率等均一定。保证乘客不会目的地不跨楼。
作业2:保持每栋楼各一个电梯,同时增加横向电梯。乘客请求满足(出发楼座 == 目的楼座)+ (出发楼层 == 目的楼层) = 1。通俗讲乘客请求一定是横向或纵向的。可动态增加电梯,电梯无可达性限制。保证横向请求出现前该层必存在横向电梯。
作业3:乘客请求更改为(出发楼座 == 目的楼座)+ (出发楼层 == 目的楼层) > 0,即可能存在既跨楼层又跨楼座的情况。
一、第一次作业
1 作业整体思路
本次作业只包含五个互不干扰的电梯,开发相对简单,使用生产者消费者模式协调即可。
2 架构设计
2.1 UML图
classDiagram class Thread class Input{ -WaitQueue waitQueue +run() } class WaitQueue{ -HashMap passengers -boolean isFalse +addPassenger(Passenger) +getPassenger(char) ArrayList +setEnd(boolean) +isNull() boolean +needEnd() boolean +needWait() } class Scheduler { -WaitQueue allWaitQueue -HashMap buildingWaitQueues +run() +putRequest() +end() } class BuildingWaitQueue { -boolean isEnd -char building -HashMap passengers +addPassenger(Passenger) +addPassengers(ArrayList) +setEnd() +getNearRequest(int, int) ArrayList +hasTakeByPassenger(int, int, int) boolean +getNearFloor(int) int +hasPassenger(int, int) boolean +needChangeDir(int, int) boolean +getPassenger(int, int, int) ArrayList +needEnd() boolean } class Elevator { -char building -int id -int openTime -int closeTime -int moveTime -BuildingWaitQueue -int size -int nowFloor -int dir -ArrayList inElevatorPassenger +run() +look() +move(int) +open() +getOff() +getIn() +close() +hasArrivedPassenger() boolean } class Passenger{ -PersonRequest personRequest -int dir +getId() int +getFromFloor() int +getToFloor() int +getFromBuilding() char +getToBuilding() char } Thread <|-- Input Thread <|-- Scheduler Thread <|-- Elevator WaitQueue <-- Input Scheduler <-- WaitQueue BuildingWaitQueue <-- Scheduler Elevator <-- BuildingWaitQueue Passenger <.. WaitQueue Passenger <.. BuildingWaitQueue2.2 类设计目的
使用了生产者消费者模式,Input线程作为生产者向WaitQueue托盘添加请求,Scheduler线程取走WaitQueue托盘请求,同时向BuildingWaitQueue中添加请求。Elevator线程作为消费者负责读取BuildingWaitQueue处理请求。
2.3 线程安全控制
将托盘的读写方法加锁,避免出现冲突、死锁。
线程结束时层层设置Tag,处理完请求且Tag为True时即可结束。
2.4 电梯运行策略
使用了Look策略,即电梯内无乘客且当前方向上无请求时反向。
3. 程序结构分析
3.1 各类代码量
File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Code Lines | Comment Code Lindes [%] | Blank Lines | Blank Lines[%] |
---|---|---|---|---|---|---|---|
BuildingElevator.java | 193 | 181 | 0.9378238341968912 | 0 | 0.0 | 12 | 0.06217616580310881 |
BuildingWaitQueue.java | 175 | 160 | 0.9142857142857143 | 0 | 0.0 | 15 | 0.08571428571428572 |
FloorWaitQueue.java | 135 | 125 | 0.9259259259259259 | 0 | 0.0 | 10 | 0.07407407407407407 |
Input.java | 43 | 36 | 0.8372093023255814 | 0 | 0.0 | 7 | 0.16279069767441862 |
Main.java | 36 | 26 | 0.7222222222222222 | 4 | 0.1111111111111111 | 6 | 0.16666666666666666 |
Output.java | 8 | 6 | 0.75 | 0 | 0.0 | 2 | 0.25 |
Passenger.java | 72 | 61 | 0.8472222222222222 | 0 | 0.0 | 11 | 0.1527777777777778 |
Scheduler.java | 56 | 51 | 0.9107142857142857 | 0 | 0.0 | 5 | 0.08928571428571429 |
WaitQueue.java | 64 | 54 | 0.84375 | 0 | 0.0 | 10 | 0.15625 |
3.2 方法复杂度
Method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
BuildingElevator.BuildingElevator(char, int, int, int, int, int, BuildingWaitQueue, ...) | 0 | 1 | 1 | 1 |
BuildingElevator.beforeHandleTarget() | 17 | 1 | 11 | 13 |
BuildingElevator.close() | 0 | 1 | 1 | 1 |
BuildingElevator.getIn() | 5 | 1 | 4 | 4 |
BuildingElevator.getInMainRequest() | 3 | 3 | 2 | 3 |
BuildingElevator.getOff() | 4 | 1 | 4 | 4 |
BuildingElevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
BuildingElevator.look() | 19 | 3 | 10 | 14 |
BuildingElevator.move(int) | 0 | 1 | 1 | 1 |
BuildingElevator.open() | 0 | 1 | 1 | 1 |
BuildingElevator.run() | 10 | 3 | 8 | 9 |
BuildingWaitQueue.BuildingWaitQueue(char) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.addPassenger(Passenger) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.addPassengers(ArrayList |
4 | 1 | 4 | 4 |
BuildingWaitQueue.getNearFloor(int) | 13 | 2 | 8 | 10 |
BuildingWaitQueue.getNearRequest(int, int) | 1 | 2 | 1 | 2 |
BuildingWaitQueue.getPassenger(int, int, int) | 23 | 6 | 9 | 13 |
BuildingWaitQueue.hasPassenger(int, int) | 5 | 3 | 3 | 5 |
BuildingWaitQueue.hasTakeByPassenger(int, int) | 5 | 3 | 3 | 5 |
BuildingWaitQueue.isEnd() | 0 | 1 | 1 | 1 |
BuildingWaitQueue.isNull() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.needChangeDir(int, int) | 9 | 5 | 3 | 7 |
BuildingWaitQueue.needEnd() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.setEnd() | 0 | 1 | 1 | 1 |
Elevator.Elevator(char, int, int, int, int, BuildingWaitQueue, int) | 0 | 1 | 1 | 1 |
Elevator.close() | 0 | 1 | 1 | 1 |
Elevator.getIn() | 5 | 1 | 3 | 4 |
Elevator.getOff() | 4 | 1 | 4 | 4 |
Elevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
Elevator.look() | 16 | 3 | 9 | 11 |
Elevator.move(int) | 0 | 1 | 1 | 1 |
Elevator.open() | 0 | 1 | 1 | 1 |
Elevator.run() | 10 | 3 | 6 | 7 |
Elevator.setDir(int) | 0 | 1 | 1 | 1 |
Input.Input(WaitQueue, HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 0 | 1 | 1 | 1 |
Input.run() | 11 | 3 | 6 | 6 |
Main.main(String[]) | 3 | 1 | 4 | 4 |
Output.println(String) | 0 | 1 | 1 | 1 |
Passenger.Passenger(PersonRequest) | 10 | 1 | 1 | 7 |
Passenger.canTake() | 0 | 1 | 1 | 1 |
Passenger.getFromBuilding() | 0 | 1 | 1 | 1 |
Passenger.getFromFloor() | 0 | 1 | 1 | 1 |
Passenger.getHorizontalDir() | 0 | 1 | 1 | 1 |
Passenger.getId() | 0 | 1 | 1 | 1 |
Passenger.getToBuilding() | 0 | 1 | 1 | 1 |
Passenger.getToFloor() | 0 | 1 | 1 | 1 |
Passenger.getVerticalDir() | 0 | 1 | 1 | 1 |
Passenger.toString() | 0 | 1 | 1 | 1 |
Scheduler.Scheduler(WaitQueue, HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 0 | 1 | 1 | 1 |
Scheduler.end() | 2 | 1 | 3 | 3 |
Scheduler.putRequest() | 7 | 1 | 4 | 4 |
Scheduler.run() | 8 | 3 | 5 | 5 |
WaitQueue.WaitQueue() | 0 | 1 | 1 | 1 |
WaitQueue.addPassenger(PersonRequest) | 0 | 1 | 1 | 1 |
WaitQueue.getPassenger(char) | 0 | 1 | 1 | 1 |
WaitQueue.isEnd() | 0 | 1 | 1 | 1 |
WaitQueue.isNull() | 1 | 1 | 2 | 2 |
WaitQueue.needEnd() | 2 | 2 | 2 | 3 |
WaitQueue.needWait() | 3 | 1 | 3 | 3 |
WaitQueue.setEnd() | 0 | 1 | 1 | 1 |
4. 正确性、性能、架构分析
4.1 正确性
没有考虑到输出存在的线程不安全问题,在强测中没有出现问题,但在互测中被hack
4.2 性能
look算法在强测中取得了相对较高的成绩,个人认为是值得采用的。
4.3架构
后续开发体验中感觉调度器没有必要设为线程,反而徒增复杂度,本人也在第三次去掉了调度器祭天,法力无边
二、第二次作业
1 作业整体思路
本次增加了横向电梯,但对乘客请求加了较强的限制条件,故处理思路与纵向电梯相同。对于多部电梯,采用的是自由竞争的方式。
2 架构设计
2.1 UML图
classDiagram class Thread class Input{ -WaitQueue waitQueue +run() } class WaitQueue{ -HashMap passengers -boolean isFalse +addPassenger(Passenger) +getPassenger(char) ArrayList +setEnd(boolean) +isNull() boolean +needEnd() boolean +needWait() } class Scheduler { -WaitQueue allWaitQueue -HashMap buildingWaitQueues -HashMap florrWaitQueues +run() +putRequest() +end() } class BuildingWaitQueue { -boolean isEnd -char building -HashMap passengers +addPassenger(Passenger) +addPassengers(ArrayList) +setEnd() +getNearRequest(int, int) ArrayList +hasTakeByPassenger(int, int, int) boolean +getNearFloor(int) int +hasPassenger(int, int) boolean +needChangeDir(int, int) boolean +getPassenger(int, int, int) ArrayList +needEnd() boolean } class FloorWaitQueue { -boolean isEnd -char building -HashMap passengers +addPassenger(Passenger) +addPassengers(ArrayList) +setEnd() +getNearRequest(int, int) ArrayList +hasTakeByPassenger(int, int, int) boolean +getNearFloor(int) int +hasPassenger(int, int) boolean +needChangeDir(int, int) boolean +getPassenger(int, int, int) ArrayList +needEnd() boolean } class BuildingElevator { -char building -int id -int openTime -int closeTime -int moveTime -BuildingWaitQueue -int size -int nowFloor -int dir -ArrayList inElevatorPassenger +run() +look() +move(int) +open() +getOff() +getIn() +close() +hasArrivedPassenger() boolean } class FloorElevator { -char building -int id -int openTime -int closeTime -int moveTime -BuildingWaitQueue -int size -int nowFloor -int dir -ArrayList inElevatorPassenger +run() +strategy() +move(int) +open() +getOff() +getIn() +close() +hasArrivedPassenger() boolean } class Passenger{ -PersonRequest personRequest -int hordir -int verdir +getId() int +getFromFloor() int +getToFloor() int +getFromBuilding() char +getToBuilding() char +gethordir() int +getverdir() int } Thread <|-- Input Thread <|-- Scheduler Thread <|-- BuildingElevator Thread <|-- FloorElevator WaitQueue <-- Input Scheduler <-- WaitQueue BuildingWaitQueue <-- Scheduler FloorWaitQueue <-- Scheduler BuildingElevator <-- BuildingWaitQueue FloorElevator <-- FloorWaitQueue Passenger <.. WaitQueue Passenger <.. BuildingWaitQueue Passenger <.. FloorWaitQueue2.2 类设计目的
看属性不难发现,其实相当于copy了一份原elevator,本意是打算使用继承关系的,但是考虑到横向电梯与纵向电梯还是存在较大差别,最终没有选择。
2.3 电梯运行策略
纵向电梯保持不变,横向电梯因为是环状的所以跨两座楼以上的乘客不论最近方向均可捎带。
3. 程序结构分析
3.1 各类代码量
File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Code Lines | Comment Code Lindes [%] | Blank Lines | Blank Lines[%] |
---|---|---|---|---|---|---|---|
BuildingElevator.java | 176 | 163 | 0.9261363636363636 | 0 | 0.0 | 13 | 0.07386363636363637 |
BuildingWaitQueue.java | 140 | 129 | 0.9214285714285714 | 0 | 0.0 | 11 | 0.07857142857142857 |
FloorElevator.java | 177 | 164 | 0.9265536723163842 | 0 | 0.0 | 13 | 0.07344632768361582 |
FloorWaitQueue.java | 135 | 125 | 0.9259259259259259 | 0 | 0.0 | 10 | 0.07407407407407407 |
Input.java | 60 | 53 | 0.8833333333333333 | 0 | 0.0 | 7 | 0.11666666666666667 |
Main.java | 29 | 24 | 0.8275862068965517 | 0 | 0.0 | 5 | 0.1724137931034483 |
Output.java | 8 | 6 | 0.75 | 0 | 0.0 | 2 | 0.25 |
Passenger.java | 72 | 61 | 0.8472222222222222 | 0 | 0.0 | 11 | 0.1527777777777778 |
Scheduler.java | 42 | 35 | 0.8333333333333334 | 0 | 0.0 | 7 | 0.16666666666666666 |
WaitQueue.java | 64 | 54 | 0.84375 | 0 | 0.0 | 10 | 0.15625 |
3.2 方法复杂度
Method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
BuildingElevator.BuildingElevator(char, int, int, int, int, int, BuildingWaitQueue, ...) | 0 | 1 | 1 | 1 |
BuildingElevator.close() | 0 | 1 | 1 | 1 |
BuildingElevator.compete() | 7 | 1 | 7 | 7 |
BuildingElevator.getCpuTime() | 1 | 1 | 2 | 2 |
BuildingElevator.getIn() | 5 | 1 | 4 | 4 |
BuildingElevator.getInFirst(ArrayList |
2 | 1 | 3 | 3 |
BuildingElevator.getOff() | 4 | 1 | 4 | 4 |
BuildingElevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
BuildingElevator.look() | 17 | 3 | 8 | 10 |
BuildingElevator.move(int) | 0 | 1 | 1 | 1 |
BuildingElevator.open() | 0 | 1 | 1 | 1 |
BuildingElevator.run() | 10 | 3 | 6 | 7 |
BuildingWaitQueue.BuildingWaitQueue(char) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.addPassenger(Passenger) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.getNearFloor(int) | 13 | 2 | 8 | 10 |
BuildingWaitQueue.getPassenger(int, int, int) | 23 | 6 | 9 | 13 |
BuildingWaitQueue.hasPassenger(int, int) | 5 | 3 | 3 | 5 |
BuildingWaitQueue.isEnd() | 0 | 1 | 1 | 1 |
BuildingWaitQueue.isNull() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.needChangeDir(int, int) | 9 | 5 | 3 | 7 |
BuildingWaitQueue.needEnd() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.setEnd() | 0 | 1 | 1 | 1 |
FloorElevator.FloorElevator(char, int, int, int, int, int, FloorWaitQueue, ...) | 0 | 1 | 1 | 1 |
FloorElevator.close() | 0 | 1 | 1 | 1 |
FloorElevator.compete() | 7 | 1 | 7 | 7 |
FloorElevator.getDir(int, int) | 2 | 2 | 1 | 3 |
FloorElevator.getIn() | 6 | 1 | 5 | 5 |
FloorElevator.getInFirst(ArrayList |
3 | 1 | 4 | 4 |
FloorElevator.getOff() | 4 | 1 | 4 | 4 |
FloorElevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
FloorElevator.move(int) | 2 | 1 | 1 | 3 |
FloorElevator.open() | 0 | 1 | 1 | 1 |
FloorElevator.run() | 10 | 3 | 6 | 7 |
FloorElevator.strategy() | 14 | 3 | 7 | 9 |
FloorWaitQueue.FloorWaitQueue(int) | 1 | 1 | 2 | 2 |
FloorWaitQueue.addPassenger(Passenger) | 1 | 1 | 2 | 2 |
FloorWaitQueue.getNearBuilding(char) | 13 | 2 | 8 | 10 |
FloorWaitQueue.getPassenger(int, char, int) | 24 | 6 | 10 | 14 |
FloorWaitQueue.hasPassenger(int, char) | 4 | 3 | 3 | 4 |
FloorWaitQueue.isNull() | 1 | 1 | 2 | 2 |
FloorWaitQueue.needChangeDir(int) | 12 | 6 | 4 | 7 |
FloorWaitQueue.needEnd() | 1 | 1 | 2 | 2 |
FloorWaitQueue.setEnd() | 0 | 1 | 1 | 1 |
Input.Input(HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 0 | 1 | 1 | 1 |
Input.run() | 16 | 3 | 9 | 9 |
Main.main(String[]) | 3 | 1 | 4 | 4 |
Output.println(String) | 0 | 1 | 1 | 1 |
Passenger.Passenger(PersonRequest) | 10 | 1 | 1 | 7 |
Passenger.canTake() | 0 | 1 | 1 | 1 |
Passenger.getFromBuilding() | 0 | 1 | 1 | 1 |
Passenger.getFromFloor() | 0 | 1 | 1 | 1 |
Passenger.getHorizontalDir() | 0 | 1 | 1 | 1 |
Passenger.getId() | 0 | 1 | 1 | 1 |
Passenger.getToBuilding() | 0 | 1 | 1 | 1 |
Passenger.getToFloor() | 0 | 1 | 1 | 1 |
Passenger.getVerticalDir() | 0 | 1 | 1 | 1 |
Passenger.toString() | 0 | 1 | 1 | 1 |
Scheduler.Scheduler() | 0 | 1 | 1 | 1 |
Scheduler.gerInstance() | 0 | 1 | 1 | 1 |
Scheduler.initial(HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 0 | 1 | 1 | 1 |
Scheduler.putRequest(Passenger) | 2 | 1 | 2 | 2 |
Scheduler.setEnd() | 2 | 1 | 3 | 3 |
WaitQueue.WaitQueue() | 0 | 1 | 1 | 1 |
WaitQueue.addPassenger(PersonRequest) | 0 | 1 | 1 | 1 |
WaitQueue.getPassenger(char) | 0 | 1 | 1 | 1 |
WaitQueue.isEnd() | 0 | 1 | 1 | 1 |
WaitQueue.isNull() | 1 | 1 | 2 | 2 |
WaitQueue.needEnd() | 2 | 2 | 2 | 3 |
WaitQueue.needWait() | 3 | 1 | 3 | 3 |
WaitQueue.setEnd() | 0 | 1 | 1 | 1 |
三、第三次作业
1 作业整体思路
本次乘客的目的地将可能不存在直达电梯,需要换乘,实现时借鉴了上机实验的流水线模式。
2 架构设计
2.1 UML图
classDiagram class Thread class Input{ -WaitQueue waitQueue +run() } class Scheduler { -WaitQueue allWaitQueue -HashMap buildingWaitQueues -HashMap florrWaitQueues -int[][] timeGraph -int[][] eleGraph +putRequest() +end() } class BuildingWaitQueue { -boolean isEnd -char building -HashMap passengers +addPassenger(Passenger) +addPassengers(ArrayList) +setEnd() +getNearRequest(int, int) ArrayList +hasTakeByPassenger(int, int, int) boolean +getNearFloor(int) int +hasPassenger(int, int) boolean +needChangeDir(int, int) boolean +getPassenger(int, int, int) ArrayList +needEnd() boolean } class FloorWaitQueue { -boolean isEnd -char building -HashMap passengers +addPassenger(Passenger) +addPassengers(ArrayList) +setEnd() +getNearRequest(int, int) ArrayList +hasTakeByPassenger(int, int, int) boolean +getNearFloor(int) int +hasPassenger(int, int) boolean +needChangeDir(int, int) boolean +getPassenger(int, int, int) ArrayList +needEnd() boolean } class BuildingElevator { -char building -int id -int openTime -int closeTime -int moveTime -BuildingWaitQueue -int size -int nowFloor -int dir -ArrayList inElevatorPassenger +run() +look() +move(int) +open() +getOff() +getIn() +close() +hasArrivedPassenger() boolean } class FloorElevator { -char building -int id -int openTime -int closeTime -int moveTime -BuildingWaitQueue -int size -int nowFloor -int dir -ArrayList inElevatorPassenger +run() +strategy() +move(int) +open() +getOff() +getIn() +close() +hasArrivedPassenger() boolean } class Passenger{ -PersonRequest personRequest -int hordir -int verdir +getId() int +getFromFloor() int +getToFloor() int +getFromBuilding() char +getToBuilding() char +gethordir() int +getverdir() int } class Counter { +add() +release() +setEnd(boolean) +isEnd() boolean } Thread <|-- Input Thread <|-- BuildingElevator Thread <|-- FloorElevator Scheduler <-- Input BuildingWaitQueue <-- Scheduler FloorWaitQueue <-- Scheduler BuildingElevator <-- BuildingWaitQueue FloorElevator <-- FloorWaitQueue Passenger <.. BuildingWaitQueue Passenger <.. FloorWaitQueue Counter <-- Input Counter <-- BuildingElevator Counter <-- FloorElevator2.2 类设计目的
增加了Counter类控制线程结束。本次作业中输入线程结束且电梯所在楼或层等待队列为空不是结束条件,必须等待所有请求处理完毕后才能结束,所以使用Counter类计数已完成的请求和添加的请求。
2.3 电梯运行策略
本次的换乘策略为最短路径。将50个地点建模为图的节点,每次添加请求时使用dij算法寻找最短路线。
3. 程序结构分析
3.1 各类代码量
File | Total Lines | Source Code Lines | Source Code Lines[%] | Comment Code Lines | Comment Code Lindes [%] | Blank Lines | Blank Lines[%] |
---|---|---|---|---|---|---|---|
BuildingElevator.java | 188 | 169 | 0.898936170212766 | 6 | 0.031914893617021274 | 13 | 0.06914893617021277 |
BuildingWaitQueue.java | 140 | 129 | 0.9214285714285714 | 0 | 0.0 | 11 | 0.07857142857142857 |
Counter.java | 36 | 29 | 0.8055555555555556 | 0 | 0.0 | 7 | 0.19444444444444445 |
FloorElevator.java | 237 | 211 | 0.890295358649789 | 8 | 0.03375527426160337 | 18 | 0.0759493670886076 |
FloorWaitQueue.java | 184 | 173 | 0.9402173913043478 | 1 | 0.005434782608695652 | 10 | 0.05434782608695652 |
Input.java | 66 | 59 | 0.8939393939393939 | 0 | 0.0 | 7 | 0.10606060606060606 |
Main.java | 34 | 28 | 0.8235294117647058 | 0 | 0.0 | 6 | 0.17647058823529413 |
Output.java | 8 | 6 | 0.75 | 0 | 0.0 | 2 | 0.25 |
Passenger.java | 131 | 107 | 0.816793893129771 | 0 | 0.0 | 24 | 0.183206106870229 |
Scheduler.java | 262 | 247 | 0.9427480916030534 | 2 | 0.007633587786259542 | 13 | 0.04961832061068702 |
3.2 方法复杂度
Method | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
BuildingElevator.BuildingElevator(char, int, int, int, int, int, BuildingWaitQueue, ...) | 0 | 1 | 1 | 1 |
BuildingElevator.close() | 0 | 1 | 1 | 1 |
BuildingElevator.compete() | 7 | 1 | 7 | 7 |
BuildingElevator.getCpuTime() | 1 | 1 | 2 | 2 |
BuildingElevator.getIn() | 5 | 1 | 4 | 4 |
BuildingElevator.getInFirst(ArrayList |
2 | 1 | 3 | 3 |
BuildingElevator.getOff() | 12 | 1 | 6 | 6 |
BuildingElevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
BuildingElevator.look() | 17 | 3 | 8 | 10 |
BuildingElevator.move(int) | 0 | 1 | 1 | 1 |
BuildingElevator.open() | 0 | 1 | 1 | 1 |
BuildingElevator.run() | 10 | 3 | 6 | 7 |
BuildingWaitQueue.BuildingWaitQueue(char) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.addPassenger(Passenger) | 1 | 1 | 2 | 2 |
BuildingWaitQueue.getNearFloor(int) | 13 | 2 | 8 | 10 |
BuildingWaitQueue.getPassenger(int, int, int) | 23 | 6 | 9 | 13 |
BuildingWaitQueue.hasPassenger(int, int) | 5 | 3 | 3 | 5 |
BuildingWaitQueue.isEnd() | 0 | 1 | 1 | 1 |
BuildingWaitQueue.isNull() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.needChangeDir(int, int) | 9 | 5 | 3 | 7 |
BuildingWaitQueue.needEnd() | 1 | 1 | 2 | 2 |
BuildingWaitQueue.setEnd() | 0 | 1 | 1 | 1 |
Counter.Counter() | 0 | 1 | 1 | 1 |
Counter.add() | 0 | 1 | 1 | 1 |
Counter.getInstance() | 0 | 1 | 1 | 1 |
Counter.isEnd() | 1 | 1 | 1 | 2 |
Counter.release() | 1 | 1 | 2 | 2 |
Counter.setEnd(boolean) | 1 | 1 | 2 | 2 |
FloorElevator.FloorElevator(char, int, int, int, int, int, FloorWaitQueue, ...) | 0 | 1 | 1 | 1 |
FloorElevator.canOpen() | 1 | 2 | 1 | 2 |
FloorElevator.close() | 0 | 1 | 1 | 1 |
FloorElevator.compete() | 7 | 1 | 7 | 7 |
FloorElevator.getCpuTime() | 1 | 1 | 2 | 2 |
FloorElevator.getDir(int, int) | 2 | 2 | 1 | 3 |
FloorElevator.getFloor() | 0 | 1 | 1 | 1 |
FloorElevator.getIn() | 13 | 1 | 7 | 7 |
FloorElevator.getInFirst(ArrayList |
8 | 1 | 6 | 6 |
FloorElevator.getOff() | 12 | 1 | 6 | 6 |
FloorElevator.getReachAble() | 0 | 1 | 1 | 1 |
FloorElevator.hasArrivedPassenger() | 3 | 3 | 2 | 3 |
FloorElevator.isReachAble(int) | 0 | 1 | 1 | 1 |
FloorElevator.move(int) | 2 | 1 | 1 | 3 |
FloorElevator.open() | 0 | 1 | 1 | 1 |
FloorElevator.run() | 10 | 3 | 6 | 7 |
FloorElevator.strategy() | 18 | 3 | 8 | 10 |
FloorWaitQueue.FloorWaitQueue(int) | 1 | 1 | 2 | 2 |
FloorWaitQueue.addPassenger(Passenger) | 1 | 1 | 2 | 2 |
FloorWaitQueue.getNearBuilding(char, int) | 27 | 4 | 7 | 17 |
FloorWaitQueue.getPassenger(int, char, int, int) | 31 | 9 | 12 | 17 |
FloorWaitQueue.hasPassenger(int, char, int) | 13 | 6 | 9 | 11 |
FloorWaitQueue.hasReachAbleRequest(int) | 8 | 5 | 3 | 5 |
FloorWaitQueue.isNull() | 1 | 1 | 2 | 2 |
FloorWaitQueue.needChangeDir(int, int) | 16 | 7 | 5 | 9 |
FloorWaitQueue.setEnd() | 0 | 1 | 1 | 1 |
Input.Input(HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 0 | 1 | 1 | 1 |
Input.run() | 16 | 3 | 9 | 9 |
Main.main(String[]) | 3 | 1 | 4 | 4 |
Output.println(String) | 0 | 1 | 1 | 1 |
Passenger.Passenger(PersonRequest) | 0 | 1 | 1 | 1 |
Passenger.canTake() | 0 | 1 | 1 | 1 |
Passenger.getFromBuilding() | 0 | 1 | 1 | 1 |
Passenger.getFromFloor() | 0 | 1 | 1 | 1 |
Passenger.getHorizontalDir() | 0 | 1 | 1 | 1 |
Passenger.getId() | 0 | 1 | 1 | 1 |
Passenger.getNextBuilding() | 0 | 1 | 1 | 1 |
Passenger.getNextFloor() | 0 | 1 | 1 | 1 |
Passenger.getNowBuilding() | 0 | 1 | 1 | 1 |
Passenger.getNowFloor() | 0 | 1 | 1 | 1 |
Passenger.getTarHorBuilding() | 0 | 1 | 1 | 1 |
Passenger.getToBuilding() | 0 | 1 | 1 | 1 |
Passenger.getToFloor() | 0 | 1 | 1 | 1 |
Passenger.getVerticalDir() | 0 | 1 | 1 | 1 |
Passenger.isNeedChange() | 0 | 1 | 1 | 1 |
Passenger.setNeedChange(boolean) | 0 | 1 | 1 | 1 |
Passenger.setNext(int, int) | 0 | 1 | 1 | 1 |
Passenger.setNextBuilding(int) | 0 | 1 | 1 | 1 |
Passenger.setNowBuilding(int) | 0 | 1 | 1 | 1 |
Passenger.setNowFloor(int) | 0 | 1 | 1 | 1 |
Passenger.setTarHorBuilding(int) | 0 | 1 | 1 | 1 |
Passenger.toString() | 0 | 1 | 1 | 1 |
Passenger.updateDir(int, int) | 10 | 1 | 1 | 7 |
Scheduler.Scheduler() | 0 | 1 | 1 | 1 |
Scheduler.addFloorElevator(FloorElevator) | 0 | 1 | 1 | 1 |
Scheduler.gerInstance() | 0 | 1 | 1 | 1 |
Scheduler.getNext(int, int[], int) | 20 | 1 | 7 | 14 |
Scheduler.getShortPath(Passenger) | 18 | 1 | 1 | 14 |
Scheduler.initGraph() | 17 | 1 | 1 | 9 |
Scheduler.initial(HashMap<Character, BuildingWaitQueue>, HashMap<Integer, FloorWaitQueue>) | 1 | 1 | 2 | 2 |
Scheduler.putRequest(Passenger) | 13 | 1 | 10 | 10 |
Scheduler.setEnd() | 2 | 1 | 3 | 3 |
Scheduler.updateGraph(ElevatorRequest) | 62 | 1 | 17 | 22 |
四、线程协作
1. 第一、二次作业
2. 第三次作业
五、Bug分析
本人在三次作业强测中均未出现bug,在第一次作业中由于没有注意到输出的线程不安全问题在互测中被hack。由于三次作业hack策略均为黑盒测试,并没有进行白盒测试,故不多加赘述。下面谈一些自己遇到的bug以及互测中hack到的bug。
1. 个人遇到的bug
前两次作业实现过程中基本没有遇到棘手的bug,多为手抖引起的小bug,故此处多为第三次作业遇到的bug。
第三次作业遇到的bug可分为两类,第一类是线程问题,主要是在输入线程结束至全部线程结束的过程中,电梯线程一直处于轮询的状态,产生了CTLE。第二类则是关于图的算法,本人在实现拆分请求的时候是根据最短路径拆分,然后根据当前位置和第一个换乘点确定将该请求放入哪一个等待队列。但没有考虑到横向移动过程中也可能涉及多次换乘。例如横向请求A-C,而电梯1为A-B,电梯2为B-C,此时需要告知将请求拆分为先去B座,再去C座。
2. 互测hack到的点
互测中遇到的均多为线程问题,概括为两类,一类是由于线程协作不当导致不能正常结束;第二类是多个线程同时操作集和导致抛出错误。此外部分代码不能完成基本请求,以及没有正确实现第三次作业中横向电梯开关门的定制化。
六、心得体会
线程安全问题方面,本单元没有遇到过线程不安全的情况,相较于初接触多线程编程时不明白哪里应该设为同步块,哪里使用wait哪里使用notify有了很大的提升。个人认为设计时就理清哪些是共享对象就能在很大程度上避免;此外条件判断时如果存在多个条件,则需要特别注意。
关于层次化设计,我的设计怎么这么扁平呢。将一个复杂的电梯调度问题拆分到各个模块降低难度,能够有效帮助我理清思路,不至于过于混乱。
一些学习体验与对课程建议:相较于去年的多电梯加night,random,morning三模式,今年的难度明显提升了,实验时给出了两种比较有参考意义的设计模式,个人认为可以再提供一些博客之类的参考资料?第二点是在我接触到的同学中有许多同学在设计伊始对synchronized,wait,notify的使用方法还是很模糊,有的同学暴力使用notifyAll导致了CTLE,这方面的资料也可以提供一些。
一些设计过程中的心得:电梯调度策略不存在绝对的好与不好,对不同的情况性能不同,设计过程不要过于纠结,个人认为贴近生活中电梯的设计就可以取得不错的效果,毕竟这些策略已经经过了生活的检验。
标签:OO,Passenger,int,FloorElevator,BuildingWaitQueue,BUAA,boolean,2022,BuildingEleva 来源: https://www.cnblogs.com/G-YY/p/16192599.html