OO_UNIT2_SUMMARY

第一次作业

设计策略

  • 采用生产者消费者模式
    • 生产者:输入线程
    • 消费者:电梯线程
    • 托盘:采用ConcurrentLinkedQueue来储存乘客指令
  • 调度算法
    • 只是采用简单的ALS算法,在电梯人数未满且乘客的方向与电梯运行方向一致时,电梯将乘客捎带进入
    • 由于我没有将调度器单独分成一个类,因此我是在电梯线程中处理乘客请求的
      • 当乘客请求增加时,直接使用get方法将请求传入电梯线程的托盘中并唤醒电梯线程
      • 处理乘客请求的方法使用synchronized关键字修饰
      • 电梯每运行一层楼都会更换一次target,而电梯的目标设定如下:如果电梯内有人,电梯的目标就是第一个进电梯的人的目标楼层,如果电梯内没人,电梯的目 标就是第一个按下电梯楼层的人,当所到楼层有人到达时,将该请求从请求队列中删除(ConcurrentLinkedQueue可以直接删除特定对象)
  • 结束线程
    • 在乘客请求结束后传递一个变量信息给电梯线程,当电梯线程处理完所有的乘客请求(即乘客请求队列为0)并且该变量信息为真时,电梯线程结束,程序结束

度量分析

  • UML类图:

OO_UNIT2_SUMMARY_第1张图片

  • 时序图

OO_UNIT2_SUMMARY_第2张图片

  • 复杂度

OO_UNIT2_SUMMARY_第3张图片

  • 由于我将处理乘客请求以及上下乘客都放在了电梯线程的run方法中,所以电梯线程的复杂度较高,应该另外分出一个调度器类来处理乘客请求来减轻电梯线程的负担,run方法应该只放入一些顶层设计,不应该有冗余的实现方法

第二次作业

设计策略

  • 相对于第一次作业只是使用将调度策略进行了修改
    • 将target由第一次作业的从每个电梯内等待队列的第一个乘客的请求变成电梯内乘客请求队列中离当前电梯所在楼层的最短请求楼层。但是由于一个细节可能会出现bug,我将电梯内的所有请求与电梯外的所有请求进行距离的对比,但是可能会出现电梯内人已满但是target仍是本层楼梯的情况,这样电梯就会永远停留在当前楼层
    • 关于多个电梯,由于每个电梯除了编号之外其他并无差别,我只是在每一楼层对于每个电梯都进行查询,仍然只使用了单个电梯线程
    • 由于电梯有不同的类别,所以我增加了Passenger类,相对于给定的PersonRequest类我增加了elevatorId属性,即为这个乘客所乘的电梯编号

度量分析

  • UML类图

OO_UNIT2_SUMMARY_第4张图片

  • 时序图

与第一次作业类似,电梯不断地取出请求、解决请求,一些标志量每到一层就进行一次初始化,在此就不做展示

  • 复杂度

OO_UNIT2_SUMMARY_第5张图片

  • 由于第二次作业是在第一次作业的基础上迭代而成的,所以run方法的复杂度仍然高居不下,但是调度策略从之前简单的ALS变成有一点LOOK算法的味道还是对电梯性能有一定的提升的

第三次作业

设计策略

  • 相对于第二次作业我进一步修改了调度策略
    • 由于电梯有类别和编号两个属性,所以将电梯的类别属性分成电梯类别和电梯编号属性
    • 由于不同类别的电梯的承载人数不同,所以设定不同的方法判断电梯是否超载
    • 由于第二次作业我使用的是电梯单线程,所以第三次作业我仍然采用了电梯单线程的策略,由于每层楼停留时间不同,我就将如果有C电梯参与的活动的电梯停靠时间都设成了0.6秒,现在看来还是应该对程序进行进一步重构的,无论是对于时间长短还是题目本身的考察点都应该将多种电梯放进线程池中
    • 关于换乘
      • 每个乘客在进入请求队列之前都会进行一次判断,如果能进行一次送达就尽量一次送达,如果不能一次送达就在1楼或者15楼进行换乘,将乘客增加是否换乘的属性,电梯到了某一楼层对请求队列进行遍历,如果到达了目的地或者换成目的地都将乘客放下,到达换成地的乘客请求仍然保存在请求队列中,将其出发地进行修改即可

度量分析

  • UML类图

OO_UNIT2_SUMMARY_第6张图片

  • 复杂度分析

OO_UNIT2_SUMMARY_第7张图片

OO_UNIT2_SUMMARY_第8张图片

OO_UNIT2_SUMMARY_第9张图片

  • 对于不同类别的电梯的类似方法应该采取合并的方法,而我的Target类中代码出现了大量冗余的情况

Bug分析

由于在本次单元中线程安全是比较玄学的错误,而我由于线程之间的交互比较简单,交互的容器也是使用了线程安全容器,所以在线程交互中没有出现什么玄学Bug,但由于电梯作业会出现比较多的循环和判断条件,比如电梯是否已经满载,电梯的调度应该去哪一楼层时都会需要进行判断,如果条件出现错误也可能出现程序无法正常跳出的情况。

  • 第一次作业:在互测中被测出了乘客已经在电梯内但是却仍然上电梯的情况,是由于条件缺少的原因
  • 第二次作业:在强测中被测出LOOK算法中可能出现电梯内人员已满但是仍然停靠在该层的情况
  • 第三次作业:由于运行时间的原因出现了较多的错误,后期可能会考虑重构

由于在线程构建中主要还是在考虑个人代码的一些架构,在互测中没有发现他人的bug。

心得体会

虽然本单元没有像第一单元那样次次重构,但是我在第一次作业中遇到了较大的困难,在周六上午才提交通过,所以希望之后的课程可以将第一单元的难度稍微放低一些。之后的作业虽然在线程安全方面大同小异,但是如果想拿比较高的性能分的话对于算法的要求可能较高。总的来说,跟第一单元的体验还是完全不同的,感觉对于个人的能力方面也是不小的提升与挑战,希望之后的课程自己也能够尽心尽力吧。

你可能感兴趣的:(OO_UNIT2_SUMMARY)