BUAA-OO-U2-Summary
BUAA-OO-U2-Summary
1 问题描述
本单元任务主要是实现一个多线程的电梯调度系统。
实际场景是BUAA新主楼的 A B C D E
五个座,每个座均有10层,楼座按顺序构成一个环;
其间存在两种电梯:横向(同一层,不同座间移动) 和 纵向(同一座,不同层间移动),电梯的移动速度,载客量,可达楼座等参数可设置;
对于每个乘客,会在某一时刻进入等待队列,表明自己的出发楼层和楼座以及目的楼层和楼座,等待电梯承载;
输入的命令有两种:添加电梯 和 添加乘客 ,提供足够的信息;
目标是把每个乘客从出发位置载至目的位置,尽量让时间最短。
2 整体结构
本单元的实验中,采用以下结构进行调度:
其中,allocator
主要进行请求的拉取和乘客、电梯的分配操作;
Elevator
主要进行电梯当前状态与参数的存储、从当前座/层的等待队列中拉取和释放乘客,仍需换乘的乘客丢回 allocator
继续处理;
Advisor
是每个电梯拥有一个、根据当前电梯和电梯所在VisitorQueue
的状态对电梯行为进行控制的模块;
VisitorQueue
共15个,10层+5座 各有一个,是主要的synchronized
块;
Output
是为了保证输出线程安全的synchronized
块。
各部分协作图如下:
3 捎带策略
捎带策略有纵向和横向电梯之分:
对于纵向电梯,采用LOOK算法
,即向一个方向移动至最远的请求或目的地,中途接取同方向的请求,前方无请求时,调转方向继续移动。
对于横向电梯,由于楼座仅五个且构成环,因此直接进行单方向的循环移动,接取沿途所有的乘客。
对于需要进行换乘的乘客,在allocator
内进行路线判断:
- 寻找最近的可以到达目标楼座的楼层,将乘客下一地点定为该楼层并放入该楼座的纵向等待队列中;
- 若本层即可到达目标楼座,将乘客下一地点定为目标楼座并放入该层的横向等待队列中;
- 若当前楼座即为目标楼座,将乘客下一地点定为目标楼层并放入该座的纵向等待队列中。
4 迭代过程
三次迭代中,调度系统的整体结构没有变化,主要变化在于:
- 新增增加电梯的请求;
- 新增换乘判断逻辑;
- 新增电梯参数的自定义初始化。
5 强测总结
三次强测中,第三次强测出了意外情况:增加电梯可达楼座的情况下,Advisor
中有一处是否接取乘客的判断没有修改,导致横向电梯出现接取不该接取乘客,该乘客也无法出门(电梯吃人)的情况。
6 互测总结
互测中,前两次均未出现bug,第三次互测中由于上述bug被hack得很惨;
除此之外,还有等待队列中由于notifyAll
的滥用,导致当前队列没有乘客时,两个电梯互相notify
,导致CPU时间爆炸的情况。
7 个人总结
本单元个人认为最大的问题在于迭代时没有进行修改汇总,导致修改遗漏的出现,以后要多注意这一点。