OO第二单元总结

OO第二单元总结

前言:

第二单元作业终于结束了。多线程作业对我个人来说挑战挺大的,从编写代码,到测试都需要用到很多新的知识。

第一次作业是最难的一次,初次接触多线程,基本语法都不熟悉,边查边试,最后比起设计出锁来,更像是试出来的,还好没有错误。

第二次作业有一处锁用错了,使强测出现了一次超时。

第三次作业,让我想把自己打死,我写了定时输入和检测结果正确性的程序辅助测试,然后我就犯懒了,没有进行充分或者不充分的测试,结果一处很明显的调度粗心让我直接没进互测屋,暂不细说,下面我还要就此骂自己很多次。

 

 

设计策略:

第一次作业:

本次作业由三个线程构成,主线程,队列线程和电梯线程。

主线程和队列线程的共享变量为外部等待队列,与队列线程无共享变量。主线程接受输入后传入到队列线程的外部等待队列中。

队列线程中保存有电梯内乘客队列与电梯外乘客队列,用于控制乘客进出。

电梯线程中配有一个调度器,用于控制电梯升降。

队列线程与电梯线程之间的共享变量为电梯内外队列与电梯能否进入标志,同时对程序结束进行了特殊处理。

当然,事后证明队列线程完全是多此一举。

 

第二次作业:

本次作业由一个主线程和每个电梯一个线程构成。

主线程与电梯线程之间的共享对象为电梯(以电梯为锁),主线程接受输入,再将输入送入每个电梯线程中。

与第一次作业相比,相当于每个电梯与内置的队列线程进行了和并,在电梯线程内部执行对分配输入的全部操作。

 

第三次作业:

本次作业由一个主线程和每个电梯一个线程构成。

各线程见的共享变量为每部电梯的外部等待队列,每当有请求输入时,添加电梯或Queue类中的操作将该请求送入指定电梯的等待队列中。

如果遇到换乘情况,该电梯线程用Queue类中的方法将其送入下一部电梯的等待队列中。

此外,对输出线程也进行了保护。

 

策略分析:

个人感觉自己的设计中线程间的共享变量很少,用到的锁也不多,不容易出现死锁或线程不安全情况(虽然也出现过)。

 

 

从设计原则角度检查设计并分析可扩展性:

SOLID原则(本次作业自己的设计中不涉及里氏替换原则、接口分离原则以及依赖倒置原则):

单一责任原则:

第一次作业中Queue线程与电梯线程纠缠不清,像是乱写,主函数倒是相对独立。

第二次作业主类用于接受输入并分配给电梯线程,电梯类用于存电梯相关信息和运行,电梯怎么运行在调度类中,主类与电梯责任单一,电梯与调度变量交换较多,不过每个调度器都是为相应电梯服务的,这样的交换并不影响,责任还是相对单一的。

第三次作业主类用于接收输入,建电梯,Queue类用于把乘客分到相应电梯中,电梯和其调度器用于电梯内的操作,责任单一性较好。

 

开放封闭原则:

本人开放封闭原则实现的不够好,三次作业基本都是在举动的类上改动,增加新请求时不是增加新类处理。不过类内部函数功能有区分,修改需求时只需要修改特定函数

 

可扩展性分析:

本人设计基本思路是将任务分配到各个电梯内解决。在扩展时,如果功能局限于每个电梯内部,修改较为容易。如果功能涉及大量电梯协同,修改较为复杂。

 

 

基于度量分析自己的程序结构:

第一次作业:

 

 

 

 

 

 

 

分析:

Queses中运行和查找楼层复杂度较高,因为寻找电梯楼层算法和人员进出判断都在这里面,这两处复杂是较为合理的。

之后的作业中,电梯楼层的寻找由电梯线程接管。

 

协作图:

 

 

 

第二次作业:

 

 

 

 

 

分析:

因为主类基本把人送进电梯就不管事了,所以主要任务都在电梯的调度器内完成。

除输出外,电梯的调度仍是最复杂的地方。因为编码风格方法行数的限制,我将调度算法拆分在了几个函数里,算法复杂度较高的函数基本都是调度函数的一部分。

 

协作图:

 

 

 

第三次作业:

 

 

 

 

 

 

 

分析:

调度算法复杂度一如既往的高。

除此之外,由于涉及换乘等,将人送入电梯不能简单的使用均摊方法了。

因此增加的判断人进什么电梯的方法复杂度较高。

其余方法复杂度较为正常。

 

协作图:

 

 

 

 

程序bug分析:

第一次作业中强测和互测未发现bug,写代码时,电梯可能出现最后门没关上的情况,后修复。还出现过因未使用线程安全容器造成的bug,改用线程安全容器后修复。

第二次作业强测错了一个点。结束输入时,唤醒的应该是电梯的锁,但我代码中写成了电梯等待队列的锁,导致线程未能唤醒,进而最后电梯线程没有结束。

第三次作业强测几乎挂完了,原因不是线程安全问题,而是调度问题。我对调度进行修改时,有两处判断捎带,我却只修改了一处,造成人进不去电梯,真实时间超时。这种bug多测试就能发现,不应该出现这样的错误。

 

 

发现bug采用的策略:

1、定时输入:多线程程序bug复现需要定时输入辅助,我写了两种定时输入的方法。第一次是将分析时间输出的程序打包成jar,再通过管道输入。后来觉得这样很麻烦,改为了内部一个线程负责输入。

2、检测程序:根据指导书,编写了一个可以根据输入和运行结果判断程序运行是否正确的程序。

3、阅读代码,分析逻辑,查找bug。

4、我要是真的多构造数据测试一点,哪怕一点点,第三次作业就不会进不了互测屋了。吸取教训,多多测试。

5、我还是不明白为什么自己都写了辅助检测的那么多东西,还是不好好检测。

 

 

心得体会:

1、减少进程间的不必要共享变量能很大程度避免线程安全问题的产生。

2、不同类,类中不同方法分工要独立明确。

3、多测试!多测试!多测试!多测试!多测试!多测试!多测试!多测试!多测试!

posted @ 2020-04-18 11:16  孙亦琦  阅读(130)  评论(0编辑  收藏  举报