OO第二单元总结

OO第二单元作业总结

一、前言

    在OO第二单元,我以电梯为载体进行了Java多线程的学习和编写。分析一部电梯的运行过程,我识别出了并发行为模式,即请求的发生和电梯的运行,这两个过程应齐头并进,共同运行。这就要求我使用多线程来完成这一单元的作业。接下来,我将分别分析和总结这三次电梯作业。

二、第五次作业

(一)任务摘要

    本次作业任务为单部多线程傻瓜调度(FAFS)电梯的模拟。电梯的类型为目的选层电梯,即每个乘客在各自所在楼层输入自己的目的楼层。一位乘客可抽象为一个电梯请求,为 id-FROM-x-TO-y 。FAFS调度策略是指按照请求进入系统的顺序,依次按照顺序逐个执行运送任务。

(二)要点分析

    本次作业难度较小,主要难点是理解和实践多线程的交互、识别出哪些对象行为需要设计为线程以及处理电梯与请求之间的协作关系。

(三)架构设计

    (1)主要思路:

        本次作业我采取了以下方案为主要思路进行设计:将请求队列放在调度器端,模拟器不断将请求推送到调度器的请求队列中,电梯不断去获得请求,一旦获得请求,就去执行,执行完毕再去获得下一个请求。采用生产者-托盘-消费者(Producer-Tray-Consumer)模式,调度器充当了一个Tray的角色,是输入线程和电梯之间的共享对象。

    (2)类图:

        分析:第五次作业我写了四个类。一个Mainclass主类,一个输入Input类,一个调度器Dispatcher类,一个电梯Elevator类。其中,Input和Elevator是线程各自做着输入请求和运送乘客的工作,它们共享一个调度器对象,构造时需要传入此参数。调度器类中有get和put两个synchronized方法(加锁),保证输入线程和电梯线程不同时对请求队列进行存取,维护了线程的安全。

    (3)复杂度分析表

        i)Method metrics

        ii)Class metrics

        分析:电梯线程的run()方法复杂度很高,因为是用比较面向过程的方法来实现电梯的运送乘客的过程。首先用while循环到达from楼层,开门进人关门,再用同样的方法将人送走。这一套流程下来,方法的复杂度就很高。

    (4)分析自己程序的bug

   这次作业在强测和互测中均未被测出bug。

 三、第六次作业

(一)任务摘要

    本次作业的任务为单部多线程可捎带调度(ALS)电梯的模拟,新增主请求被捎带请求两个概念。首先选择主请求,再按照一定的规则选择被捎带的请求,从而达到降低运行时间的目的。

(二)要点分析

    本次作业难度有所增加,关键是是主请求如何更换和被捎带请求如何选择,以及带来的一系列优化问题和线程安全问题。需要我进一步理解线程之间的交互,并针对多线程进行测试设计。

(三)架构设计

    (1)主要思路:

        电梯对调度器公布状态变化(当前楼层、主请求状态),并以某个特定的频率根据自身状态变化扫描requestqueue来变更主请求并且选取其中的可捎带请求。在本次作业中,我选择让电梯每arrive一层,就与dispatcher中的请求队列交互一次,来进行捎带队列的变化。

    (2)类图:

        分析:本次的架构还是之前的四个类,在Dispatcher类传入了电梯变量以获得电梯当前的楼层以及主请求的状态(电梯运行状态),新增了getpick方法,在Elevator类中调用getpick方法可以获得当前主请求下能被捎带的请求组成的队列。在Elevator类中新增了picksomeone方法,以主请求为骨架,在运送主请求途中调用getpick以及picksome方法完成对捎带请求的运送。

    (3)复杂度分析表

        i)Method metrics

        ii)Class metrics

         分析:由于将主请求更换的操作写在了Elevator类的run()方法里,导致方法的复杂度进一步升高。并且,每层都对被捎带请求进行操作,需要进行较为复杂的判断来决定是否进人或出人,产生了许多ifelse这样的判断语句块,所以picksomeone方法的复杂度也较高。

    (4)分析自己程序的bug

        这次作业在强测中产生了许多bug,得分较低,并未进入互测。在bug修复过程中,我发现这些bug其实是3个同质bug。列举如下:

  1.处理捎带队列的时候,未考虑到乘客状态,导致出现乘客已经进入了电梯,抵达相应楼层后再进一次的错误。

  解决方案:增加一个inelevator队列,每当乘客进入电梯的时候将其add到此队列,离开时剔除,以此作为乘客是否进入电梯的依据。当乘客不在电梯内,才进行in操作,当乘客在电梯内,才进行out操作。

  2.openthedoor和closethedoor的方法中,未考虑到电梯门的当前状态,导致电梯的门开门之后再开门一次的错误。

  解决方案:增加一个Boolean类型的变量isopen来表示电梯门当前状态。为true表示电梯门开,为false表示电梯门关闭,当电梯门开启时,才进行close操作,当电梯门关闭时,才进行open操作。

  3.出现电梯门还未关闭就移动的现象。

  解决方案:在arrive操作之前进行close操作。由于上个bug的修复,不会出现close两次的情况。

四、第七次作业

(一)任务摘要

    本次作业的任务为多部多线程智能(SS)调度电梯的模拟。本次多部电梯的可停靠楼层,运行时间,最大载客量都不相同。电梯数量:3部,分别编号为ABC。电梯可停靠楼层:A: -3, -2, -1, 1, 15-20,B: -2, -1, 1, 2, 4-15,C: 1, 3, 5, 7, 9, 11, 13, 15。电梯上升或下降一层的时间:A: 0.4s,B: 0.5s,C: 0.6s。电梯最大载客量(轿厢容量)A:6名乘客,B:8名乘客,C:7名乘客。

(二)要点分析

    本次设计的线程关系更为复杂,需要进行线程工作状态更为精确的控制。线程安全问题进一步加深。具体的要解决的点有:某些请求不可直达,某些请求只有特定电梯可达,电梯客满之后的处理,优化处理等。

(三)架构设计

    (1)主要思路:

        设置三个电梯线程,各自拥有一个调度器对象。对于每个请求,先分析是否可以通过某一部电梯直达,如果可以,则分配给相应的调度器,如果不可以,按照一定的逻辑将其分割成两条请求,先后按照可直达请求执行即可。当电梯满员后,不进人。基本架构和第六次作业相同。

    (2)类图:

        分析:本次仍然是四个类。其实这样的设计并不好,我在输入线程Input里增加了分配请求的操作,这是一个败笔。当输入停止后,输入线程由于afterdevide队列的牵制不能立刻停止,导致输入线程轮询停止条件,大大增加了cpu时间。

    (3)复杂度分析表

        i)Method metrics

       ii)Class metrics

        分析:这次我一定程度上的降低了电梯方法的复杂度(比上次好),降低了Elevator类与其他类的耦合度。但是由于将指令分配的工作放在了Input线程里,增加了Input类的复杂度。其他的线程保持与上次作业类似。

    (4)分析自己程序的bug:

      这次作业我的强测和互测均未被测出bug。但是我的性能分很低。我思考了一下方面优化的可能性:

       1.电梯每次上下乘客时,先下后上,降低因为最大载客量的约束造成的性能损失。

       2.当一个请求分配给某个电梯满员时,应该去寻求分配给另个电梯的可能。我并未考虑这一点。

  3.动态化换乘模式。我当前的换成是静态的,固定在某几个楼层换乘。而动态的换乘可以优化性能。

五、发现别人bug所采取的策略

    第一次我没有进行hack,因为没想到可以找的点。第二次我未进互测,第三次我发现别人bug的策略是这样的:首先检查他们的线程安全问题,当输入异常终止或在特殊的时间点投放输入的时候,是否会产生行为的错乱。接着利用第二次强测的数据,在此基础上进行修改,分别根据各类换乘的情况依次排查程序正确性,覆盖所有的换乘可能如A换B,A换C等。最后,我设置了一些相对极端的数据,比如-3到20层这类数据,来检验程序是否能在规定的时间将乘客运送至目的地。

六、Applying Creational Pattern

    具体而言,我应用创造模式有:调度器的构造使用单例模式,整体是生产者-消费者模式。总体而言,我这单元的设计比上一个单元考虑的东西更多,更为主动,尽我所能的去“面向对象”设计,代码的复用性还可以,也没有进行太颠覆性的重构。希望在下一个单元的学习中能够更好地应用各种创造模式。

七、心得体会

    在线程安全的方面,我给可能产生非原子性操作的方法加了synchronized,将其锁住。我们学习多线程,必须要面对线程安全问题,对这类问题进行更深入的了解,从而避免或减少线程安全问题,这种设计,让我感受到了实际工程设计中的严谨性。在设计原则方面,我的原则是先保证程序的正确性,再考虑性能问题。把精力放在最重要的事情上。

    经历了第一单元的洗礼,第二单元做的稍微能够不那么仓皇失措了。虽然第六次作业强测炸得一塌糊涂,心态崩了一段时间以外,其他的体验都还行。渐渐适应了OO课程的节奏,程序也会提早写好,第一单元是ddl玩家,第二单元这一现象好很多,因为害怕最后关头出幺蛾子,所以总是努力赶在周一晚上把中测的点过了。这样一来,我还有星期二的时间可以进行一定的优化。我希望下一单元我可以更好地安排时间,不要做得那么紧张。同时,我这单元和其他人的交流变得更多了,这样可以扩展我的思维,使我的思路不那么闭塞,从而更高效的解决一些问题。

 

posted @ 2019-04-24 21:07  江流君  阅读(154)  评论(2编辑  收藏  举报