OO Unit2总结

欧阳晓宇-23373273 2025-04-16 12:41:58

同步块的设置和锁的选择

  • 同步块的设置主要用于两个队列类:WaitQueue类以及ProcessQueue类之中的各种方法,用synchronized关键字修饰,在调用时还需要进行notifyAll();操作。除此之外还在ElevatorThread类中的run方法有相关的使用,主要是用synchronized关键字修饰电梯线程对应的请求队列。

  • 锁的选择主要是使用了ReentrantLock,主要是用在每个电梯线程对应的Strategy类即策略类中相关需要进行等待固定时间的方法之中,例如电梯的移动,开关门,以及后续两次作业新增的临时调度以及双轿厢改造之中。保证这个方法不能被多个线程同时使用。

总的来说三次作业中对于同步块的设置和锁的选择都是使用以上的思路,没有太大的区别。

 

调度器设计与调度策略

  • 由于第一次作业对于个人请求有指定的电梯,故在这次作业中调度器不需要有过多的处理,只需要将个人请求分配给对应的电梯线程即可。

  • 从第二次作业开始个人请求不再有指定的电梯,同时还加入了相对应的RECEIVE的输出,用于指出将该个人请求分配给了哪一个电梯线程。同时由于还加入了临时调度和双轿厢改造等新的请求,导致可能会有部分个人请求在未到达指定楼层时就被赶下了电梯,需要将其看作新的请求再次分配。

    • 在第二次作业中由于在临时调度之后电梯可移动楼层没有发生改变,即仍然可以完成全部请求,故对于临时调度被踢下电梯的个人请求,不返回分配器再次进行分配,而是直接返回该电梯线程的等待队列之中,在临时调度完成之后由该电梯再次RECEIVE请求并完成请求。

    • 在第三次作业中由于新增了双轿厢请求,会导致电梯的可移动楼层发生改变,故不再能沿用第二次作业中的做法,对于未到达指定楼层的请求必须传回分配器线程重新进行分配,为此我新增了一个容器用于存储所有个人请求的ID,判断该容器是否为空,即是否所有个人请求均已完成来判断是否要结束分配器线程。

  • 对于后两次作业请求没有指定电梯,故需要对调度器使用一定的分配策略,根据往届学长的博客以及相关的讨论,主流的分配策略有以下几种:自由竞争,均分策略,人数策略,影子电梯以及调参策略。由于个人能力有限以及时间制约,本人并没有去实现效率较好的影子电梯以及调参策略,而是选择了较为简单且容易实现的均分策略。最后就结果来说还是得到了不算差的性能分,至少都上90分了,个人觉得性能分的事情只有保证了正确性的前提下再去追求才是合理的,正确性都没有还想什么性能分,就本人的水平性能分就是图一乐的东西罢了。

  • 最后关于调度策略是如何适应时间、电量等多个性能指标的,实话实说根本没有去考虑过时间、电量等这些个指标,基本上都是代码写完,调试完发现没有什么问题之后就结束了,不会专门往这方面上凹,基本上都是听天由命。

 

作业分析

UML类图

第一次作业

 

第二次作业

 

第三次作业

 

UML协作图(sequence diagram)

第一次作业

 

第二,三次作业

 

内容分析

稳定的内容

三次作业中较为稳定的内容主要是在整体的架构上,主要表现在几个线程类:InputThread类,DispatchThread类以及ElevatorThread类的主要设计上,以及两个队列类:WaitQueue类,ProcessQueue类,三次作业下来基本没有对这几个部分的内容进行太大的修改。

易变的内容

这个单元的作业中最易变的内容应该是策略类:Strategy类,随着作业的迭代以及新要求的增加,该类的行数从第一次作业仅有个人请求的300行就可以完成;到第二次作业中加入临时调度请求使行数增加到了350行;最后再到第三次作业中加入了双轿厢改造请求,使策略类的复杂度达到了顶峰,来到了450行,还是在进行了部分重构的情况下。主要的改变在于对不同请求的处理以及bug的修复上。

除此之外还有一部分改变的是分配线程:DispatchThread类,主要是因为后两次作业中不指定请求的电梯,故需要对调度线程进行一定的修改,但是由于本人使用的是平均分配策略。所以在该部分也没有特别大的修改。

除了修改的类之外还增加两个新的类:UpdateBarrierPool类以及TransferLock类,均是在第三次作业中新增了双轿厢改造之后增加的类。

 

双轿厢改造的实现

第三次作业中新增了双轿厢改造的请求,主要有两个难点:

  1. 对要改造的两个电梯同时输出改造信息。

  2. 保证改造之后的两个电梯不会相撞。

同步开始改造

本人在第三次作业中新增了UpdateBarrierPool类,主要实现如下:

public class UpdateBarrierPool {
    public static final ConcurrentHashMap<UpdateRequest, CyclicBarrier>
            barrierMap = new ConcurrentHashMap<>();
}

即存储了一个barrier,用于保证两个电梯线程在接受到双轿厢改造时,第一个处理该改造请求的电梯线程先在输出改造信息前wait,等待后一个电梯线程到达,在后一个电梯线程到达的时候再唤醒前面在等待的电梯线程,实现同步开始改造,同时还要注意改造信息只需要输出一次,故可以指定一台电梯线程输出相应的改造信息。

改造之后电梯不会相撞

本人最开始的想法是若保证电梯不会停留在换乘楼层,即一个电梯到达换乘楼层完成操作之后的第一时间就离开换乘楼层,后来发现这个思路无法保证两个电梯不会相撞。

故后来本人的想法是若改造后的电梯将要前往换乘楼层,先判断是否会相撞,即另一台电梯是否在换乘楼层,若在换乘楼层,则该电梯在此处等待,知道另一电梯离开换乘楼层时唤醒该电梯,使该电梯可以前往换乘楼层而不想撞。同时还有一个需要注意的点就是若一台电梯到达换乘楼层之后没有请求,即即将进入wait状态等待新的请求时,需要在wait之前就将该电梯移走,避免该电梯在换乘楼层wait,导致出错。

为了实现以上思路本人新增了一个TransferLock类,主要实现如下:

public class TransferLock {
    public static final Object LOCK = new Object();
}

同时在策略类中新增了一个avoidCrash方法,用于在电梯将到达下一层楼前进行判断,若判断到将要发生电梯相撞时,使用TransferLock将该电梯线程锁住,等待另一电梯线程移走。

 

bug分析

出现过的bug

本人在第一次作业中由于对于请求队列的获取方式有问题,导致出现了ConcurrentModificationException这个喜闻乐道的bug,经过多次的提交以及长时间的检查代码,本人发现是在对电梯线程所有请求的获取上出现了问题,将获取队列改为获取队列的拷贝之后,bug就解决了,但是本人还是被这样的bug折磨了很久。

同时本人还在第一次作业和第三次作业中出现了CTLE的bug,主要原因是在CPU的轮询上,在第一次作业中主要时因为在分配线程中无法一时将该电梯的所有请求全部分配到电梯线程中而导致的轮询,在每次分配前先sleep几毫秒就可以解决这个bug,同样的第三次作业中也是因为在请求队伍输入完毕但是线程中的请求还未处理完毕时出现了轮询的bug,同样采取以上的方法修改之后就可以解决这个bug。

除此之外还有一些小的设计上的bug,如第二次作业中出现的电梯满载但主请求还未上电梯时电梯行为出错的bug,在进行一点修改之后也可以轻松的解决。

多线程程序的debug方法

多线程的bug十分的诡异,甚至有时候难以复现,故需要花更多的时间在bug的寻找和修复上。

本人也没能找到太好的解决方法,我认为首先要确定在何处出现该bug,寻找一组能够较稳定复现该bug的样例,然后通过分析样例及相关报错,之后才能对bug进行修改。本人认为寻找多线程的bug往往比修改bug更为困难。

 

心得体会

线程安全

对于多线程程序来说线程安全十分的重要,若是线程安全出现了问题,往往会在意想不到的地方出现意想不到的错误。故保证线程安全可能比线程的设计更为重要,主要保证线程安全的方法就是对可能会出现线程安全的方法,对象加同步块,对可能出现线程安全的代码加锁。

在出现线程安全问题时要寻找能够复现bug的样例,仔细思考何处可能会出现线程安全的问题。同时完成代码的编写之后也要积极去用大量的样例进行测试,保证没有线程安全的问题的出现。

层次化设计

本人的作业架构主要参考了第三次实验上给出的实验代码的架构,总的来说这个架构还是较为符合本单元的作业,同时结合作业的要求也就其进行了一定的层次化调整,以使其更为符合作业的要求以及便于之后作业的迭代。

总的来说层次化设计是十分的重要的,好的设计能够使你在得到新的作业要求的时候更好的下手,同时也可以保证让你的代码不要这么容易的变成屎山,保证了代码的可读性,便于debug。

总结

这个单元可以说是十分的恶心,在拿到第一次作业时甚至一度不知道该如何下手,在查阅了大量往届学长的博客以及学习相关知识,在加上第三次实验的内容之后,才算是抓住了一点边,慢慢的把代码憋了出来。

后两次作业迭代新增的请求也是十分的恶心,需要考虑到方方面面,还要保证代码不会出错。

经过这一个月三次作业外加两次实验的折磨下来,或许对多线程程序的编写有了一定的了解,但整体来说还是不知道了解了什么。再加上时不时出错的课程平台,总的来说这个单元的体验并不好。

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

269

社区成员

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

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