301
社区成员
发帖
与我相关
我的任务
分享可以选择对方法上锁,也可以选择对对象上锁。这里本人采用的是对方法上锁,在调用RequestTable对象的任意读写方法都用synchronized上锁,保证最多只有一个线程访问或修改读写队列。其实这个在第二次实验之后发现可以改成读写锁,但并不知道如何封装。原有的对RequestTable加锁方法对外是透明的,在其他地方不需要过多地考虑锁和同步问题,于是没改。
需要设计的策略细分下来应该有两种,一个是调度器如何将请求分配给电梯,另一个是电梯面对分配给自己的请求采用怎样的方式处理。
先说第二个,这个是沿用往届的LOOK算法,具体实现如下:
(摘自Hyggge‘s Blog调度策略)
第一个调度器分配,其实根据题目不同会有不同的“最优”调度方法。本人调度器分配方式从调参变到均分,尝试影子电梯未遂。
第一次作业中,由于题目非常贴心地给出了电梯id,所以不存在调度器的说法,直接由InputHandler交给电梯即可。


这里RequestTable又是ArrayList又是HashMap是因为一开始用ArrayList发现RTLE了,以为是数据结构问题于是改成:处理总队列的时候按照ArrayList先进先出,在电梯处理的时候按照HashMap,人在外面则以FromFloor作索引,人在电梯里则以ToFloor为索引。
第二次作业意料之中地取消了宝宝椅,请求到来时不给指定电梯id,并且意料之外地ban掉了自由竞争,电梯必须输出Receive有明确的目标才能移动。
本人在该作业中采用调参策略,简单来讲就是衡量各个电梯当前所在的位置、方向和容量进行评估,分配给得分最高的电梯。
主要修改及新增:


第三次作业主要新增的就是将普通电梯改为双轿厢电梯。
本人在这次作业采用了非常神奇(yuchun)的设计,即如果电梯类收到了双轿厢重置请求,则该电梯执行调度器的功能,管理两个subElevator。这样设计的好处是对于以前的调度器而言,电梯数量始终为6,分配给双轿厢的处理方式对外不可见,起到了很好的封装作用。
subElevator和普通的电梯区别主要在:
上层的逻辑基本没变,并且双轿厢电梯把人放到换层楼层后并不是扔回大请求队列,而是直接由电梯调度器给伙伴电梯,结束判断条件也只需要从电梯开始调整,而不需要动上层框架(优雅但不是很优雅)。


这次作业没啥bug,毕竟均分的特点就是牺牲一些性能分,换来绝对的安全。
但是从上一次的惨败中吸取了教训:sunglasses:掌握了hack技巧:
双轿厢防撞车参考了讨论区的分享,设置一个Flag类管理换乘层是否被占用。每个两个电梯共享一个Flag Occupied,但看讨论区发现不对这好像就是锁……所以其实不用自己写……?
三次作业成绩太精彩了,第一次自以为有效的优化实际完全错误导致性能分极低(在大家都很高的情况下),第二次终于选择照顾性能分了但又WA了一个点导致分还是低且在互测被狠狠攻击,第三次遂摆烂选择牺牲性能分换取正确性。
一直采用的防御性编程导致似乎没有出现很多线性安全问题,倒是保证输出顺序正确以及正确且正常结束这两个部分让人很伤神。
感觉整体架构还挺清晰的所以每次新增功能也没有更改很多代码(不像第一单元重构重构重构……)而且双轿厢的设计感觉比往届的横向电梯更合理一些,新增功能增加得很开心。
但乘客能不能再灵活一些啊!都只有一层楼了就不能自己走吗!?