BUAA_OO Unit 2

刘祖权-22371221 学生 2024-04-19 15:32:32

一、整体架构

UML 类图

img1


(白色类为 HW1 即存在的类,蓝色类为 HW2 时添加,绿色类为 HW3 时添加)

逐步变化:

  1. 采用生产者-消费者模式,共享对象为 waitQueueProcess 负责管理电梯的运行
  2. 在第五次作业中,由于没有 reset 请求,waitQueue 与 电梯 requestQueue 的功能相同,只需设计一个类
  3. 在第六次作业中,加入 reset 请求,从 Queue 中引出两个子类:WaitQueueElevatorQueue,两者相同的属性 isEnd 与方法 setEnd 保留在 Queue 中,其他功能在子类中分别实现
  4. 第七次作业中,加入双轿厢电梯,从 Process 中引出两个子类:NormalProcessDoubleCarProcess,同样的,电梯最基础的运行功能保留在 Process 中,其他功能在子类中分别实现。此外,新增 Manager,用以监视、管理所有的实体对象,并负责乘客的分配

未来扩展能力:

若新增不同运行策略的电梯,只要电梯自身属性没有改变,只需创造新的 Process 子类,用以管理该电梯的运行。值得注意的是,对于类似双轿厢电梯这样,电梯之间会相互影响的情况,需要谨慎考虑可能发生的线程安全问题。

UML 协作图

img

稳定与易变内容

稳定内容:

  1. 生产者-消费者模式
  2. 电梯的基本属性,开关门、上下乘客、移动等操作
  3. waitQueue 的属性与操作

易变内容:

  1. Schedule 中的分配策略
  2. Process 中的运行策略
  3. ScheduleProcess 间的协调关系(如 reset 可能导致请求返回到 waitQueue 中)

二、同步块的设置和锁的选择

Queue

​生产者与消费者的共享对象,为保证线程安全,几乎所有方法全部添加了 synchronized 关键字,因为它们都需要对队列进行读写操作。但 geAll() 例外,因为该方法在分配 request 时被调用,返回 queue 中的 request 个数,用以评估电梯的得分,是只读的且在数值上有一点偏差影响不大。也考虑过采用读写锁提高效率,但出现了不曾预料的线程安全问题,一时没找到原因,遂放弃。

Elevator

​在执行 DoubleCarReset 时,采用重置原电梯,并在 Monitor.elevators 中加入一个新电梯的方式。而在重置原电梯时,Schedule 还在不停的分配 request。为了避免可能发生的线程安全问题,将电梯的 initDC()(重置为双轿厢电梯时调用的方法)、evaluate() (分配 request 时评估电梯得分的方法)添加 synchronized 关键字,保证电梯不会在“变身”的途中被分配 request。

​全部采用 synchronized 关键字很方便,但是相应的效率会降低。之后若有时间会尝试效率更高的锁。

三、双轿厢不碰撞

​双轿厢电梯有一个属性为 buddy,即同一井道内的另一个轿厢。电梯在移动前,会判断另一个轿厢是否停在自己的目标楼层。若是,则发出请求,使另一个轿厢离开;否则直接移动。

三、bug分析

My bug

  1. HW5 中,由于电梯捎带策略没有仔细设计,导致有多名乘客等待接送时,没有采取最优的路线,故超时。
  2. HW6 中,在分配 request 时,只考虑了电梯自身的参数及电梯上的乘客,没有考虑电梯对应的 queue 中已接受的请求,故在极端样例中将所有请求都分配给了同一个电梯,导致超时。
  3. HW7 中因潜在的线程安全问题被 hack。此前在评测机上跑了多次,都没有出现相关问题,从逻辑上分析也未找到直接原因,为 Elevator.initDC() 添加 synchronized 关键字后,bug 不再出现。(其实不加也能通过,就假装找到问题原因了吧

Debug 方法

  1. 在多线程程序中,print 大法难以见效,往往加入一个 print 语句就会使得本就不高的复现概率雪上加霜。对于评测集上出现 RTLE 出现的样例,我在本地多次尝试复现未果(无论加不加 print)。索性直接将带有 print 的程序提交到评测机上,再检查其中报错为 RTLE 的样例与输出
  2. 若实在无法复现 bug,需要针对出错样例及错误输出,依照代码推断可能的错误原因,若代码上难以直接发现,可以编写简单,但具有相同情况的样例尝试复现 bug

四、心得体会

​很好,又活过一个单元 (>_<)

​在第五次作业中,对于线程安全问题还没有较为清晰的认知,只需要参考第四次实验,照葫芦画瓢即可。在第六次与第七次作业中可谓是受尽折磨,常常对 bug 原因百思不得其解,并怒斥电脑为何不能复现 bug …… 经过多个夜晚的冥思苦想,以及在纸上进行多次演练后,终于有所感悟

​此外,对于电梯调度策略,随机分配似乎不失为一种有效的方法,并且不需要对电梯的当前状态进行读取。若想进一步提高性能,也可以根据一些参数(如电梯的运行速度)进行加权随机分配。想起自己写的愚蠢的分配算法,真是悔不当初。

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

301

社区成员

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

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