2024春OO课程二单元总结

姜涵章-21375212 学生 2024-04-19 14:59:35

@

2024春OO课程二单元总结

  • HW5
  • 架构
  • 共享对象
  • 调度策略
  • uml
  • HW6
  • 架构
  • 问题一 对于正在RESET的电梯,调度时是否还需要考虑它?
  • 问题二 电梯收到reset指令后,要将电梯内的乘客赶下车,并且将已经分配给他的乘客还给调度器,重新调度
  • 调度策略
  • 问题一 如何使用影子电梯
  • 问题二 如何计算性能
  • 问题三 为什么不能设置成单目标?比如只考虑时间或耗电量
  • 问题四 如何评判电梯的时间与耗电量
  • 电梯运行策略
  • uml
  • HW7
  • 架构
  • 共享对象
  • 调度策略
  • 问题 如何分配?如何计算每个电梯的性能分
  • 补偿计算方法
  • uml
  • bug分析
  • 心得体会
  • 线程安全
  • 层次化设计
  • 感谢

HW5

架构

img

共享对象

hw5的架构中,共享对象较少,只有inputQueue和passengerOut是共享对象,我选择构造一个线程安全的类RequestQueue,将需要保护的读写方法在类中加锁**(synchronized)**,需要使用时直接调用类的方法,不再需要关注线程安全问题。

调度策略

由于输入中已经规定了电梯号,所以调度器直接根据输入的电梯号来分配即可

uml

img

HW6

架构

img

第二次作业加入了reset,且需要自己写调度器,现在面临两个问题:

问题一 对于正在RESET的电梯,调度时是否还需要考虑它?
  • 需要,因为有一批因RESET而强制下电梯的人正在被重新调度,他们所位于的楼层一定刚好就是正在RESET的电梯的楼层,此电梯很有可能还是这些乘客的最优电梯

  • 而且,如果直接放弃所有正在RESET的电梯,当五个电梯都在RESET时,乘客会全部被分到一个电梯,性能爆炸。

  • 实现方法,为电梯新增属性stopResetTime,开始reset的时候,将它的值设置为System.currentTimeMills() + 1200,影子电梯计算时间时,多加上stopResetTime -System.currentTimeMills()即可。电梯运行策略不变,修改难度不大

由于正在reset的电梯是不能输出receive的,所以我实现了一个receiveQueue类,当调度器分配请求给电梯的时候,如果电梯处于reset状态,则先不输出revceive,而是将乘客请求先暂存再receiveQueue中,等待电梯reset结束之后,将receiveQueue中的乘客请求统一输出。

问题二 电梯收到reset指令后,要将电梯内的乘客赶下车,并且将已经分配给他的乘客还给调度器,重新调度
  • 问题的实现很简单,但经过分析可以发现一个小问题,调度器线程的结束条件为:请求队列为空且输出线程结束。但是,由于电梯在reset之后,还有可能将请求送回请求队列,即请求队列的来源不再只有输出线程,需要对调度器的结束条件做一个修改,即新加一个条件:当所有收到reset电梯已经将请求送回请求队列,才能让调度器结束。但是这个条件并不好判断,需要调度器去访问电梯的私有变量,为了尽量减少共享变量的数量,我实现了一个中转站队列transferQueue,电梯接收到reset指令后,分别将passengerIn和passengerOut的乘客存入中转站,最后再将中转站的请求送给调度器,而调度器只需要判断中转站时候中转完毕即可,避免了对电梯私有变量的直接访问。

调度策略

这次需要自己写调度策略,我选择了较难实现但是性能高的影子电梯,以下是一些问题和解决方法

问题一 如何使用影子电梯

将每一条指令当作最后一条,计算分配给六个电梯的结果,看哪一个电梯的综合性能最好

问题二 如何计算性能

最直接的方法是直接按照课程组给的型能分计算方法,分为三个目标来计算。但是这种方法过于繁琐,且base分未知,只能自行猜测,最终结果并没有想象中的准确,方法性价比不高。我选则将三目标转化为双目标,将等待时间和系统时间合并为时间性能。耗电量单独作为另一个性能,综合考量每一个电梯

问题三 为什么不能设置成单目标?比如只考虑时间或耗电量

假如只考虑时间,那么电梯会尽量吧每个人都尽早送到,很可能出现来了六个请求,而调度器将他们分别分配给了六部电梯,耗电量剧增。

假如只考虑耗电量,电梯会尽量顺路接人,很可能将所有的请求分给同一部电梯,导致等待时间和系统时间非常长。

而且根据课程组型能分的计算方法,当某一项指标过于优秀时,性能分有上限,不会再高,所以我们应当综合的提升各个指标,而不是只专注一一个目标

问题四 如何评判电梯的时间与耗电量
  • 当一条乘客请求到来时,还是把它当作最后一条请求,分别计算分配给六部电梯后,电梯送完所有乘客所需要的时间t耗电量w1

  • 再分别计算六部电梯不带这个乘客的耗电量w0

  • T与目标一**(时间)成正相关,W1-W0**与目标二(耗电量)呈正相关

  • 最终根据公式** score_i = TIME_RATE * t_i + POWER_RATE * (w1_i – w0_i)**

  • 计算每个电梯的评分,取score_i最低的电梯作为目标电梯

电梯运行策略

  • 影子电梯只能帮我们选择以当前的电梯运行策略为前提下,最好的分配方案,所以电梯的运行策略决定了我们性能的上限,同样至关重要

  • 我采用的是稍加改良版的look算法

  • 传统look算法:电梯的运行方向上没有请求且电梯内为空时转向,接客时只接乘客请求方向与电梯当前方向一致的乘客。

  • 改进版:在接客时,优先接最早到的乘客

  • 电梯超载时能尽量避免某一乘客的超长时间等待

uml

img

HW7

架构

img

第三次作业加入了双轿厢,共享对象被迫增加,线程数也相应增加,影子电梯的计算方法也需要修改

共享对象

每组电梯的AB电梯之间存在需要共享的数据,即占位flag,当某电梯运行到换乘层时,flag置1,离开时flag置0

进入换乘层之前需确保flag==0,与RequestQueue类似,建立线程安全的Flag类,实现上述两个功能

img

调度策略

  • 难点:乘客可能需要中途换乘,影子电梯模拟时无法预知换乘给哪部电梯

  • 强制规定当乘客分配给双轿厢电梯时,只能由该电梯换乘?

  • 缺少灵活性,且假如A电梯将乘客送至换乘站,B电梯可能需要从远处以空状态运行到换乘层来接乘客,浪费电梯资源

  • 放弃这种方法,改为到达换乘站后乘客强制下车,重新加入inputQueue,重新分配

问题 如何分配?如何计算每个电梯的性能分
  • 例如一个1-11层的请求分给换乘层为6A轿厢电梯,无法一次送达,若仍按之前的方法计算(计算电梯送完所有乘客后所花费的时间和电量),那么非双轿厢电梯一定要比双轿厢电梯所耗费的时间和电量都多。

  • 这里的送完不等于送达,双轿厢电梯在换乘层将乘客赶出来也算送完

  • 解决:将双轿厢电梯计算出的结果加一个补偿,补偿的计算方法如下

补偿计算方法

假如乘客请求为x-y,双轿厢电梯换乘层为a,将它送到a层后强制下电梯,那么乘客还需要移动y-x层才能到达目的地
在模拟电梯不带人运行时,计算出所有电梯的平均每移动一层开关门的次数times。则可以估算,乘客还需要移动y-x层,期间电梯开关门(y-x)*times次。
根据以上两个估算值,估算出乘客到达目的地还需要的时间和耗电量,作为补偿加在原来的结果上。

uml

img

bug分析

为了便于观察每个电梯的运行情况,我用空格和颜色进行了区分,同时在输出类中用flag控制是否打开此功能,提交前将flag置false即可,不需要频繁的注释

img

检查死锁方面,我在wait()前后,或是synchronized块的前后输出“wait{n}”和“back{n}”,这样在程序卡住时,我只需看一下哪个wait后面没有back,即可定位死锁的位置。

img


img

心得体会

线程安全

经历了多线程的之后,我意识到写代码前提前构思的重要性,不然debug会很麻烦

层次化设计

层次化见前面的图

感谢

最后感谢老师,所有辛勤付出的oo助教们,以及为我提供思路的舍友和朋友。

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

301

社区成员

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

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