OO第二单元总结-电梯

苏嘉娴-78066009 2024-04-16 17:57:02

OO第二单元

oo第二单元是模拟多线程实时电梯系统,并熟悉多线程的设计方法,熟悉线程、锁、共享对象之间的关系。

  • 总体架构

 

 本单元的电梯架构主要由Controller(控制器)、RequestQueue(请求队列)和Elevator(电梯)组成。InputThread将输入的请求Request加入到AllRequestQueue请求队列中,Controller从请求队列中获取请求并将请求分配给合适的电梯加入到电梯的请求队列中。电梯再从请求队列中取出请求作为电梯的mainRequest主请求,从而开始运行电梯。

在第五和第六次作业中,线程有输入线程,控制器线程,电梯线程(共6个)。第七次作业添加了一个EleController类对同一个id的电梯进行管理。若遇到重置电梯为双轿厢电梯的请求则增加多一个电梯线程。本单元采用的模式是生产者和消费者模式,其中输入线程充当了生产者而控制器线程和电梯线程则是同时作为生产者和消费者。AllRequestQueue和RequestQueue则充当了生产者和消费者模式中的托盘角色。通过设计同步块和锁来保证电梯正常运行。

  • 同步控制块的设置和锁的选择

第五次作业中,同步块只有RequestQueue,因为它作为共享对象,实例对象有两个,一个是总请求队列waitQueue,还有每个电梯的请求队列requestQueue。同步块用sychronize加锁,保证多个线程访问共享对象不会发生冲突。对每个共享对象的方法添加sychronized,保证共享对象每次只会被一个线程访问以避免数据竞争。当有线程访问共享对象,若共享对象被别的线程访问,线程就会被挂起等待锁的释放。若线程不满足条件则用wait()方法将线程挂起,等待其他方法用notifyAll()唤醒。

  • 电梯调度策略

本单元三次作业中的调度器均为Controller类。Controller将waitQueue队列中等待的人按照一定的策略分配到每个电梯的请求队列中。由于第五次作业乘客指定了电梯,所以只需要将请求分配到相应的电梯就可以了。第六和第七次作业则需要自行设计调度器将请求分配给合适的电梯。在第六次和第七次作业中采用的策略时平均分配策略,将所有人平均的分配到每个电梯中。

电梯运行策略

电梯的运行策略采用的是look算法:

  1. 若电梯中主请求要到达的楼层在当前电梯的方向一直则运行方向保持不变

  2. 若请求队列中有乘客的出发楼层在电梯运行的方向前面,则保持不变

  3. 若请求队列中没有乘客的出发楼层在电梯运行的方向前面或电梯满人,则转换反向

  4. 若电梯无人且请求队列中没有请求则电梯原地等待

第五次作业

本次作业需要构建多部电梯,将乘客请求分配给电梯,在规定的时间内将所有的乘客送至目的地。

第五次作业相对比较简单,架构沿用了实验的架构并且顺利的完成作业。对于下一次作业的扩展,本作业新增了Controller类用于实现下一次作业的电梯分配策略。

bug与debug

在本次作业中没被hack成功也没发现别人的bug。

第六次作业

新增内容:

  1. 乘客不再指定电梯,需设计调度器分配电梯完成乘客请求。
  2. 电梯在运行一段时间以后,可能会接收到重置指令的电梯需要尽快完成重置动作,再投入使用
  3. 增加了RECEIVE约束,需要输出RECEIVE来说明乘客请求分配情况。

本次作业的架构与上次作业相差不大,做了一些调整,新增了EleThread类,电梯不再作为线程。

reset实现

在接受到reset请求,电梯将在两层内进行重置。当电梯内有乘客,电梯将会在下一层将乘客全部送出。然后未完成的请求将作为新请求加入到AllreuqestQueue请求再为请求重新分配电梯。

bug与debug

在互测中被hack了一个bug,就是当5部电梯同时RESET时,所有请求将会分配给唯一一部没RESET的电梯导致RTLE。解决的办法是当有多部电梯同时在RESET时将暂停分配请求直到电梯完成RESET。

第七次作业

新增内容:

  1. 第二类重置请求将电梯修改为双轿厢电梯。当重置完成后,轿厢 A 默认初始在换乘楼层的下面一层,轿厢B默认初始换乘楼层的上面一层。重置为双轿厢电梯后该电梯将不会再有reset请求。

本次作业新增了一个ElevatorController类,用于管理相同id的电梯。当电梯遇到重置为双轿厢电梯请求时,会新增一个电梯和电梯线程并加入到ElevatorController类中以便于进行管理。

乘客换层

电梯换层与reset送出乘客相识,若乘客需要换层,当电梯抵达换层楼层将会将乘客全部送出。然后未完成的请求将作为新请求加入到AllreuqestQueue请求再为请求重新分配电梯。

避免双轿厢电梯相撞

当电梯将要前往换层楼层时,将会调用ElevatorController中的goTransferFloor()方法,表示电梯想要前往换层楼层。若换层楼层没有电梯,则该电梯获得锁直到电梯调用了leaveTransferFloor()方法表示电梯离开了换层楼层来释放锁。若换层楼层有电梯则进行wait(),直到另外一部电梯调用了leaveTransferFloor()方法来唤醒等待的电梯。

bug与debug

在互测中被hack了一个bug,由于缺少判断条件,导致电梯在接受到重置请求后多移动了一层导致reset没来两层内完成。

心得体会

本次作业需要注意的问题是线程安全的问题。在本单元的作业中遇到了线程进入wait状态而没被唤醒导致rtle的问题。因此,需要适时的notify唤醒线程以避免所有线程都陷入等待状态。由于线程的bug难以复现,导致很难验证线程的安全。

...全文
104 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧