类 | Qu | Rlist | Elv | ElvMotor |
---|---|---|---|---|
IN | run() | |||
Trans | Close(), tr(), run() | |||
Rlist | add(), done(), qry(), poll() | |||
Elv | setClsd(), add(), done(), redir(),port(), run() | redir(), port(), wk(), run() | ||
ElvMotor | flr(), gate(), up(), dn(), open(), close(), cmd(), run() |
Qu | Trans | Elv | ElvMotor | |
---|---|---|---|---|
IN | run() | |||
Trans | close(), launch(), nalloc(), run() | Newelv(), launch(), run() | Launch() | |
Elv | porti(), run() | wtf(), dir(), launch(), tp(), dis(), done(), ori(),wk(), run() | ||
ElvMotor | flr(), gate(), cmd(), up(), dn(), run() |
Qu | Elv | |
---|---|---|
Base | req(), alloc() | alloc() |
Elv | release() | go(), open(), close(), port()s |
调度器仅负责把请求从主等待队列转储到电梯等待队列中,直接用synchronized块解决即可。
调度器负责把电梯“发射”至目标楼层,目标楼层可以是出现请求的楼层,也可以是约定好当没有可分配请求时应去往的停泊楼层。
调度器有主动入口和被动入口:新增请求时输入线程激活调度器,使用主动入口;电梯轿厢为空时调用调度方法,使用被动入口。
调度器每隔200ms扫描一遍等待队列,刷新每个请求分配的电梯号码,刷新每个电梯的目标楼层。依次trylock所有电梯,若成功则signal()。除sleep(200)外,调度器永不休眠,因而也不需要被唤醒。调度器给每个电梯设置目标楼层时赋值语句是原子语句,不需要加锁。
电梯自身调度是魔改的莫队算法,希望利用请求出现的局部性,优先在一段小区间里往返送人。人少的时候效果极差。类图中Rlist类是莫队实现的主要基础。在此基础上增加电梯非常容易,只要继承电梯类,并重写与停靠楼层、运行速度相关的方法即可,调度器也只需改为转储时向不同电梯写入请求即可。
性能:失败;可拓展性:良好。
使用共享等待队列,Rlist被弱化为仅包含判断方向是否相同、比较距离远近的静态方法。共享队列 + 调度器分配目标楼层 的架构兼具抢人和分配两种思路的优势,性能优秀。但共享队列带来了一些线程安全问题,其解决较复杂。由于调度时认为各电梯之间没有属性上的差异,因此增加电梯种类可能导致调度器出现较大改动。
性能:优秀;可拓展性:一般。
共享队列plus。调度器每隔200ms刷新一次,重新分配请求,设置每部电梯的目标楼层。每个请求增加权限部分,可以只允许指定电梯载客,考虑了每部电梯之间属性差异。通过删除调度器唤醒电梯以外的所有唤醒操作、删除与等待队列或电梯线程无关的所有临界区,成功杜绝了线程安全问题。实现了简单的换乘,但总体性能似乎没有不换乘好。
性能:较优秀;可拓展性:尚可。
没有互测中发现的bug
强测第9个点运行过慢的"bug"
特征:贪心算法在极端情况下失效
Class | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Trans.nearq() | 5 | 4 | 2 | 5 |
位置:Trans(调度器)类,nearq方法
修复:qu.size()>=6则改成裸的抢人
本地以1/30的频率稳定复现调度器唤醒电梯时被阻塞,导致电梯请求调度时发生死锁的bug。
特征:在需要系统原语的地方使用了两步判定
Class | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Trans.run() | 22 | 4 | 10 | 11 |
位置:Trans(调度器)类,run方法
修复:改用trylock()
print过于靠后的bug
特征:代码长度7,圈复杂度1
Class | CogC | Ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Elv.Stop.release() | 1 | 1 | 2 | 2 |
位置:Elv(电梯类)->Stop子类,release方法
修复:print语句移到该方法第一行
分配时发生数组越界的bug
特征:未考虑参数在执行过程中被其他线程修改的情况
Class | CogC | ev(G) | iv(G) | v(G) |
---|---|---|---|---|
Trans.run() | 39 | 8 | 13 | 16 |
位置:Base(调度器)类,alloc方法
修复:cnt改为tmp.length
原文:https://www.cnblogs.com/fallqs/p/14695358.html