BUAA_OO_Unit2总结

前言

本单元要模拟一个类似北京航空航天大学新主楼的电梯系统,楼座内有多部电梯,电梯可以在楼座内1-11层之间运行。系统从标准输入中读入乘客请求信息(起点层,终点楼层),请求调度器会根据此时电梯运行情况(电梯所在楼层,运行方向等)将乘客请求合理分配给某部电梯,然后被分配请求的电梯会经过上下行,开关门,乘客进入/离开电梯等动作将乘客从起点层运送到终点层。

第五次作业

本次作业指定了乘客乘坐的电梯,因此不需要考虑给乘客分配电梯的策略。

UML类图

UML协作图

线程设计

使用了生产者-消费者模式

输入线程(InputHandler)作为生产者,从终端不断获得请求。调度器线程(Controller)负责调度,把输入线程收到的请求送到请求池(RequestTable)中。电梯线程(Elevator)作为消费者,从请求池(RequesetTable)中获取请求并不断地进行状态更新。

运行策略

通过阅读往届学长学姐的博客,采用了广泛使用的Look算法,具体的思想如下:

  • 如果电梯没人

    • 如果没请求,则等待

    • 如果有请求,沿原方向前进(原来是等待则沿另一个方向前进)

  • 如果电梯有人

    • 判断当前是否需要开门

    • 如果不用开门,则沿原方向前进

同步块与锁

由于本次作业的共享对象只有请求池类(RequesetTable),因此对请求池中的所有方法上锁即可保证线程安全。

第六次作业

本次作业的迭代改变了两点:

1.不再指定乘客对应的电梯,因此需要自己设计乘客分配策略。

2.新增了电梯的重置(Reset)功能。

UML类图

UML协作图

调度方案

由于本人在设计方案时还不知道“影子电梯”的方法,而且对性能没有极致的追求,所以最终采用了静态模拟的方法作为调度方案。

该方法的基本思想是根据请求给每部电梯都计算一个相应的分数,然后将请求分配给分数最高的电梯。不同于影子电梯的地方在于只能考虑到当前请求,不能将历史的请求都考虑到。该方法的优点在于其性能分只比影子电梯的方法低一点,但更能保证正确性同时实现更为简单。

具体的实现方法是设置几个权重,本人主要考虑的是该电梯接到该乘客所需的时间和电梯目前等待队列的人数,根据这些计算结果对电梯的性能做一个整体评估,最终选择评分最高的那一个电梯。

电梯重置

电梯重置有以下几个注意要点:

1.重置前要清空电梯内的请求以及电梯外的请求,同时要在重置结束后重新分配这些请求。注意有些请求可能需要修改起始楼层。

2.电梯重置过程中是不能接收请求的,所以要采用wait-notify的方法保证线程安全。

第七次作业

本次作业的迭代在于新增了一种重置操作,可以将电梯设置成双厢电梯,上下两部分分别各有一部电梯运行。

UML类图

UML协作图

双轿厢电梯

本人的双轿厢电梯的实现方法为将原先的电梯设置为双轿厢电梯的下半部分,同时在调度器中新增一个电梯线程,作为双轿厢电梯的上半部分。

双轿厢电梯的增加也导致了请求分配策略的修改。选择电梯时要剔除一些情况,例如请求起始层低于公共层的请求不能分配给上半部分的电梯。同时由于调度器中新增了增加电梯的方法,因此需要对调度器类中的部分方法上锁,保证线程安全。

关于如何防止两部分电梯相撞,我是修改了电梯wait的条件,使得电梯到达公共层后,无论此时有没有请求,都让电梯移动一层,使公共层恢复空闲状态。这个地方也借鉴了讨论区的一个优化,即某电梯如果等待时间大于等于移动一次的时间可以在另一个子电梯移出公共层的一瞬间直接进入。

bug分析

我在第五次作业表现良好,强测与互测均没有被发现bug。但是在第六次作业翻了车,强测爆了三个点,互测被hack了10次😭。一个bug是分配策略的问题,当同一时间遇到大量请求,我会把很多请求分配给同一个电梯,导致超时。另一个bug是电梯停止运行判断条件的缺少,导致可能会出现某电梯已经停止运行但过一段时间又有请求分配给了这个电梯。

第七次作业我强测没有出错,但互测被hack了几个点,问题在于当遇到六个电梯同时进行双厢重置时,某个请求会被分配错电梯,导致该电梯一直无法接到这个乘客。解决办法是修改了双厢电梯的重置方法,使得遇到上述情况时选择电梯时能遍历到所有电梯。

心得体会

线程安全方面,在能保证线程安全的前提下,尽量要少加锁,否则不仅可能会导致死锁,还有可能影响性能分。

层次化设计方面,要明确知道每个类的功能是什么,并且每个类只实现一个功能,同时在多线程设计过程中要明确有哪些线程,处理好线程之间的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值