OO第二单元总结博客

第五次作业

1.1 思路分析

第五次作业实现了五个楼座每个楼座单个电梯,以基本的消费者生产者模型为思路,一个输入类作为生产者线程,五个楼座的总共五个单部电梯作为五个消费者。构建自己的一个存放请求的线程安全队列,每个楼座对应一个队列,生产者线程将输入判断后添加到对应的队列中,电梯作为消费者从对应队列中取出请求并完成,在本次作业中,对于每一个队列,只有一个输入类向其中添加,一个电梯从其中拿出请求,可以较为容易得保证实现线程安全。在调度策略上,我采用标准的ALS策略。在同步块的设置上,对我自己构建的队列的除了构造方法外的每个方法都用了synsynchronized修饰,而其它的类与线程就不用再考虑锁的问题了。

1.2 结构分析

 

 

 

 

整体的处理流程为Reader类读入请求,并解析请求放到相应楼座的等待队列中,电梯从各自对应的等待队列中取出请求,采用ALS策略,每到达一个新的楼层判断遍历等待队列选择是否需要捎带

度量分析

在构建的队列中因为要实现ALS策略的遍历时,我将遍历的方法放在了队列的对象中,方法的复杂度较高,在代码风格检测时也因为方法的长度问题导致扣分

1.3 bug分析

本次作业中没有发现自己代码的bug,也没有被hack,也没有hack到其他人,在hack他人时主要也是采取随机生成的数据来hack。

1.4 感想与收获

在本次作业中熟悉了生产者消费者模型,对多线程有了初步的了解,初步掌握了锁的应用,如何确保线程安全。

第六次作业

2.1思路分析

第六次作业较第五次作业增加了很多东西,首先是增加了“横向电梯”这一要求。从一楼到十楼可以看成是新增了10个楼座,横向电梯与竖向电梯运行逻辑没有很大差别。在每个楼层也如楼座一般建立一个队列。本次作业的请求都可以由竖向电梯或横向电梯一次性完成,在输入类判断相应的请求放到对应的队列中再由电梯从队列中取到请求去完成。其次是电梯会动态增加,难点在于动态增加电梯后一个队列就会对应多个消费者,需要考虑线程安全的问题。在电梯的调度策略上,因为一层或一座可能有多个电梯,电梯运行上采用ALS策略,请求的分配则是电梯自由竞争请求。在同步块的设置上与第五次作业相同,对自己构建的队列的除了构造方法外的每个方法都用了synsynchronized修饰,而其它的类与线程就不用再考虑锁的问题了。

2.2 结构分析

 

 

 

 

整体的处理流程为Reader类读入请求,如果请求是增加电梯就放入相对应的类型的调度器中处理,如果正常请求,判断请求是不同楼层的还是不同楼座的,放入两个不同的调度器中,调度器在将请求放到对应楼座或楼层的等待队列中,电梯从各自对应的等待队列中取出请求,采用ALS策略,每到达一个新的楼层判断遍历等待队列选择是否需要捎带。

度量分析

在本次作业中新加了横向电梯,横向电梯我用了一个新的类来实现,而在代码上,横向电梯和纵向电梯大多代码其实是重复的,在代码的可复用性上不是很好,并且调度器只是作为一个“中转站”的效果,很多功能实际是在队列类中实现,队列类中的代码除了基本的添加移除外,在ALS策略遍历的方法冗杂重复。

 

2.3 bug分析

在本次作业中被hack到了一个bug,搭乘横向电梯的人数超过了限制。实际是横向电梯的调度策略中,一处判断有问题而导致的,横向电梯相比于竖向电梯,因为要判断顺逆时针的问题以及可以循环的问题,所以较之竖向电梯要复杂许多。在本次hack别人时,依然采用随机生成数据的方法,但生成的数据都是集中在一个楼座或者同一个楼层中,但并没有找到同组人的bug

2.4 感想与收获

在本次作业中熟悉了怎么运用锁来确保线程的安全,本次作业在一个队列会对应多个消费者,对线程安全的控制尤为重要,通过互斥访问与同步控制来读取数据,通过线程安全的共享对象来完成线程之间的交互。

 

第七次作业

3.1思路分析

第七次作业主要新增了两个需求,一是请求可以同时跨楼层与跨楼座,就需要考虑转乘的问题。建立一个Request类,读入请求时,将请求拆分成多个请求,将第一个需要完成的请求加入到相应楼层或楼座的队列中,当完成后,通知调度器再将下一个需要完成的拆分请求加入到相应队列中,循环往复直至完成原请求。二是电梯的可搭乘人数及速度由输入决定,以及横向电梯规定了可以停靠的楼座。对于每个请求需要找出最短路径进行拆分请求,分配。在同步块设置上,除了在上次作业中用到的对自己构建的队列进行同步控制外,考虑到如何判断线程是否应该结束的问题上,在最上层的调度器中设置了两个临界变量用来判断乘客请求是否全部完成,所以对这两个变量也需要同步控制。

3.2 结构分析

 

 

 

整体的处理流程为Reader类读入请求,每读入一个新请求放入总控制器中,如果请求是增加电梯就放入相对应的类型的调度器中处理,如果正常请求,判断请求的不同类型以及规划路径分拆为多个MyRequest,放入相应的调度器中,调度器在将请求放到对应楼座或楼层的等待队列中,电梯从各自对应的等待队列中取出请求,采用ALS策略,每到达一个新的楼层判断遍历等待队列选择是否需要捎带。当电梯完成一个请求时再通知主控制器该请求完成,在主控制器中找到对应分拆请求的原请求,判断请求是否还要未完成的部分或以经完成,当所有请求都已完成且无新请求时将下层调度器以及电梯线程结束。 在性能设计上,没有考虑每个请求的最短路径,一个请求最多分拆为三个子请求,在性能上并不太好。在功能设计上,虽然能完成本次作业的要求,但如果新增加电梯种类,新增请求的种类之类的新需求,我只能如第六次作业的新增一般,再新增类,而代码却是大量重复的,很多方法也是在队列类中实现,总的说来可拓展性不是很好。

度量分析

在本次作业中的机构与代码重复问题并没有改善,类之间都是相互应用,耦合度较高。

3.3 bug分析

在本次作业中被hack到了一个bug,搭乘横向电梯的人数超过了限制。实际是横向电梯的调度策略中,一处判断有问题而导致的,横向电梯相比于竖向电梯,因为要判断顺逆时针的问题以及可以循环的问题,所以较之竖向电梯要复杂许多。

3.4 感想与收获

 这次作业是本次作业的最后一次,我对java多线程的设计有了初步的了解,能够自己独立设计一个多线程的程序,对同步控制也能较为熟练的应用。

心得体会

 经过这一单元的训练,我初步掌握了多线程编程,能够分析出哪些类需要多线程的实现,能够识别出哪些需要共享对象,并且能够给共享对象的需要同步控制的操作在合适的地方加上锁。
多线程之间的交互写作是本单元作业的主题,而如何把握多线程与同步块之间的平衡是本单元的难点,保障线程安全的首要应该是有一个好的程序架构,有好的程序架构才能清晰的找出共享对象,以及分析清楚哪些操作需要加锁实现同步控制。在本单元的学习中我只是接触到了多线程编程的大门,其他的问题怎么使用多线程,多线程的适用情境,除了消费者生产者模式外的模式还有什么。要不断深入学习,深刻理解多线程的思想,体会其中脉络。

 

 

posted @ 2022-04-29 19:09  YanG2k17  阅读(7)  评论(0编辑  收藏  举报