OO第二单元总结

OO电梯单元回顾

HW5

  • 直接上图!
  • UML

image

  • 协作图

image

可以看出,这次作业的架构非常清晰易懂,调度策略方面一开始使用的是ALS,后来用的是look,这也导致了我写的look策略中有颇有ALS的遗风。。。。

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

    • 使用synchronized方法将Scheduler中的方法锁住,防止出现异常情况。
  • 调度器设计

    • 受实验时代码的启发,一开始想把调度器设为线程,后面发现越来越复杂,又参考了几位学长的博客,便抛弃了该想法。
    • InputThread将请求加入到Scheduler中,之后以楼座为key放入到waitQueueHashmap中,电梯直接从Scheduler中取请求,若无请求,则wait
  • bug分析

    • 自己的bug主要是由于自己对于look策略没有深入了解,导致了一些强测点TLE
    • 比如五层来了请求,然后六层也来了请求,之后是四层,之后七层也来了请求,那么我的程序会先五层,然后接六层,然后接四层,然后接七层,基本上就是会卡一个循环,来回跳,这个bug出现的原因我认为还是一开始使用了ALS策略,之后对于主请求好像有些依赖。。。。这也反面说明了一开始好好设计架构的重要性
  • Hack策略

    • 发现同房间中有人输出线程不安全,会出现输出序列时间非递增的情况,以及电梯超载等情况
    • 本单元的测试我发现有许多bug难以复现

HW6

  • 先上图!!
  • UML

image

  • 协作图

image

  • 受流水线架构和主从架构的启发,本次作业新增Controller,对于ReqList这个跟上次作业的Scheduler的作用差不多

    • 策略是look+自由竞争,首先inputThread读入请求之后会先传给Controller,之后Controller会将这些请求根据不同楼层、不同楼座分发给不同的ReqList,横向电梯或纵向电梯会从ReqList中访问请求,并进行决策。
    • 模式上新采用了单例模式,ControllerOutput均为单例模式
  • 同步块的设置和锁的选择

    • 依然采用synchronized对调度器的方法进行同步设置,
  • 调度器设计

    • 请允许我再上一张图。。

      image

    • 自己的架构有点像两个调度器,首先Controller根据请求的不同楼座、不同楼层划分给不同的ReqList,若是新增电梯,则直接新增,之后电梯会从ReqList中获取请求

    • 对于获取请求这里,我一开始是想着跟第一作业一样,有两个动作,首先是判断当前模式下是否有请求,然后捎带当前楼层或楼座下的请求,后来发现这样做有一个问题,就是比如说A5层有两个请求,并且该座有两个电梯,则这两个电梯会一块上去,显然有点反人类。。。。

    • 于是我再电梯里新增了一个ArrayList类型的waitPassengers,用来存放该电梯抢到的请求,同时捎带当前楼层或楼座下的所有请求,这样做的好处是两个电梯可以同时并行运行,不必像上述所说情况那样反人类。。。。。由于我修改了Elevator这个类,也导致了自己bug的出现,唉。。。。。

    • 这样做的好处还有一个就是方便迭代开发,考虑到下次作业会换乘,对于这个架构而言,只需在InputThreadController之间加一个Parser即可

  • 架构模式

    • 这次架构类似于流水线,又类似于主从,hhh,xs
  • bug分析

    • 这次bug主要是由于在Elevator中新增了waitPassengers,然后忘了判断是否超载所造成的,强测过的点得分都挺高,有好几个100、99的,如果没有错的话,我的强测应该可以99+的,结果白白丢了40多分,直接给我干到了C roomwwwww,好可惜。。。。这次真的很难受
    • 想想其实应该是自己一开始的架构设计不太好,在迭代开发中修改了之前的内容,又或许是逻辑不严谨,我也意识到了测试很重要,但是中测两次就过了,谁会想到还会有bug,不得不说中测实在太弱了,至此我的心态已经有点崩溃了,毕竟设计了这么久。。。。

HW7

  • 上图!!!
  • UML

image

  • 协作图

image

  • 诚如第二次作业而言,这次作业新增了换乘等要求,我也如约地新增了Parser等类

    • 这次由于设计到换乘路线的问题,我新增了Parser, Route,并对于官方包提供的PersonRequest类进行了重写,对于所有横向电梯的可达信息放到AllSwitchInfo中存储。
    • 换乘策略采用了基准策略,进行静态解析,主要是出现了一些轮询、线程无法结束等问题,没有时间再去换策略了。
    • 另外对于不同速度的电梯,设置了不同的优先级,这样可以使速度更快得抢到更多的请求
  • 同步块的设置和锁的选择

    • 依然是synchronized方法进行同步
  • 调度器设计

    • 本次作业的调度器设计跟上次作业差不多,区别就是InputThread会先将请求送到Parser,若是新增电梯,则直接Controller,之后Parser会根据请求的起点和终点以及当前已有的横向电梯可达信息进行解析,最终形成Routes,并和PersonRequest形成PersonReq传入Controller中,其余跟第二次作业相同
  • 分析自己程序的bug

    • 先说说在自己测试时bug,受上次血的教训,我进行了大量的测试,发现没出现的线程问题全出现了。首先是程序无法结束,我是在Controller中存储了一个Hashmap,用来存放不同楼座、不同楼层上的Routes,在解析时有一路线就加1,然后路线结束了就减1,但是我发现有时候Controller中的Routes始终不为0,这也导致了有些线程结束不了,经发现,是由于我电梯wait的条件以及路线减1的位置不对,比如说一个路线被接收到了,但还没有结束,于是电梯就会wait,之后就无限等待了,应更改为在该路线被分配出去时就应减1,这样才不会导致无限wait,再者就是电梯吃人,原因就是由于在横向电梯接人时没有判断是否可达
    • 公测中出现的bug,首先是轮询,横向电梯应该在ReqList中没有可达请求时wait,而不是为空时才wait,其次是策略问题,我原来的策略无法在同一楼层不可达时进行换乘,最后是横向电梯接人时只判断了ToBuilding没判断FromBuilding,我也不知道当时我是怎么想的。。。

心得体会

  • 看了几篇大家写的博客,都说第二单元比第一单元简单,难道只有我一个人觉得第一单元更简单一些吗?( •̀ ω •́ )✧
  • 但我也学到了很多东西,对于多线程开发有了一点点小经验,多线程开发跟单线程开发的最主要的区别就是多线程需要考虑的东西很多,比如线程之间的竞争,是否占用CPU资源,是否可以正常结束等等。另外也学到了一些架构,比如流水线架构、主从架构、生产者-消费者架构等等,这些对于多线程的开发很重要,可以解决很多现实生活中的问题。另外通过这一单元的学习,我对于面向对象的理解更加深了。另外我也意识到了迭代开发的好处,在之后的学习和工作中,在设计时候应多考虑如何留出更多的拓展空间。
  • 虽然说这一单元扣了很多分,但也学到了很多东西,只能说利大于弊吧。还想说一句,这次图画的真爽。我身边报OO课程的人比较少,有时候问题只能自己解决,当然还有助教,在这里我想感谢一下lxh,zsm两位助教哥哥的帮忙。最后说一句:电梯月终于结束了!!!q(≧▽≦q)
posted @ 2022-05-04 12:46  theSerein  阅读(25)  评论(0编辑  收藏  举报