OO第二单元总结
1.单电梯-FCFS调度
1.1.设计策略
- 利用简单的生产者消费者模型即可实现这次的调度方案,架构设计上非常简单,具体实现上也不难,这次作业大概目的就是了解和会基本的多线程编程,但是要注意使用
wait
和notify
而不是暴力轮询,不仅会损失性能还可能产生错误.整体的架构大概就是用单例模式设置一个请求池,每次从输入得到请求就放入资源池中,而电梯每运行完一次就从资源池中取到一个请求.
1.2.uml类图和uml时序图
Persons
类用于不断接收输入的请求,Constroler
类作为资源池存储请求,Elevator
类用于从资源池中读取请求并根据请求运行,运行结束后读取下一个请求
1.3.度量分析
- 可以看出不管是方法还是各个类的复杂度都比较低,因为此次作业的架构和代码量都确实非常简单
1.4.bug分析
- 此次因为整体的架构都非常简单,所以遇到的bug比较少,但是一定要注意程序结束的时机,要确保所有的请求都被执行完并且输入1结束才真正结束
1.5.互测bug
- 此次互测几乎没有bug,而且因为没有性能分的要求所以基本上全员满分.
2.单电梯可捎带策略
2.1设计策略
- 将资源池按楼层进行存储,以出发楼层作为索引将请求分配给不同的楼层,电梯每运行到一层,就判断是否要进行捎带,捎带策略为遇到同向的请求就进行捎带,到达主请求楼层后,更新著请求,如果电梯内有(比如向上)的请求就继续向上走直到没有向上的请求了就转向,等到电梯空了,就到附近楼层取指令.
2.2uml类图和uml时序图
- 和第一次的类基本是一样的只是改了一下电梯的调度策略而已,还是
Persons
读取请求并且放入资源池然后电梯读取请求,只是对电梯进行了大的升级,让其有较高的自动化.
2.3度量分析
- 虽然第二次的方法数比起第一次有了非常大的提升,类的复杂度也有了不小的增加,但是其实整体的架构并没有什么大的改变,主要是为了支持电梯的捎带,对电梯类进行了很大的升级,基本上所有的功能都集成在电梯类内部,其他的还是无脑的提取指令然后放入资源池.
2.4bug分析
- 因为这一次还是采用了老一套的架构,所以在线程安全方面倒是每遇见什么bug,关键是电梯类能不能很好的执行它的功能,大多数的bug也都是出在这里面,因为不管是调度策略,还是运行策略,都是电梯自己完成的.
2.5互测bug分析
- 在互测中很多人都进行了架构上的改变,另外增加一个调度器线程,调度交给调度器解决而电梯的功能则是非常简单无脑的运行,所以因为新增的调度器线程,所以会增加更多的线程安全隐患,但是尽管如此,这也是一个更好的方案,因为便于第三次作业的完成.
3.多部多线程智能(SS)调度电梯
3.1设计策略
- 三类线程:分别是
input
线程用于不断读取输入的请求并且放入资源池,Scheduler
线程用于调度,将资源池中的请求分发给电梯,3个elevator
线程用于执行请求.
- 指令分割策略:经过观察可以发现,所有的电梯都可以到达1层和15层,所以可以将指令经过1或者15作为中转,当然这只是一个傻瓜策略,只是因为这种实现起来最为简单,所以考虑时间因素笔者这里采取了这个傻瓜策略.
- 指令分配策略:经过分析可以发现,几乎所有的请求都可以通过B电梯直接完成,所以到时候肯定B电梯是最忙的,A电梯主要是到达15层以上的楼层,而C电梯负责分流,而且注意利用A和C电梯对B进行分流.
- 电梯创建方式:采用了工厂模式创建A,B,C三类电梯,当然具体的创建过程是传入参数进行创建而不是采用继承
3.2uml类图和uml时序图
- 首先是采用了工厂模式进行A,B,C三类电梯的创建,然后
RequestPool
类是资源池,Schduler
类是调度器,三个elevator
类是三类电梯,Print
类只是单纯的为了输出的线程安全所设置的,即所有的输出都锁住它,最后是Main
类作为入口
3.3度量分析
- 其实这次新增的内容主要是Scheduler类,它要完成指令拆分,指令分配,电梯调度等非常重要,困难又十分复杂的功能,所以这个类是我们这次的重点,至于电梯,资源池等的变化倒是不是很大.
3.4bug分析
- 这次因为线程之间的通信交互等十分复杂,所以在刚开始的时候遇到了很多非常奇妙的bug,同时由于指令拆分所以又造成了许多的线程安全问题,其实这次出现bug的关键点就是因为指令拆分问题,没有指令拆分整个线程的工作就显得十分清晰.
3.5互测bug
- 这次在互测中,虽然遇到了bug但是都是那种不可复现的,也就是所谓的线程安全bug,调试起来也非常困难,直接打印又会造成一些影响导致bug不复现,关键是提交之后也因为不可复现而出现空刀的情况
4.测试方法总结
- 相比于增加断点测试,直接打印一些信息的效果要更好一些
- 直接打印会造成一些问题,对线程造成一些影响,所以可以使用log进行测试
- 可以使用log4j进行log测试,但是注意不能将log信息全部打印,而是要挑选必要的信息进行打印
- 这次的自动化测试(评测姬)大部分是用的同学的代码,然后在其基础上进行一些修改然后使用,这次的多线程测试十分困难,如果没有自动化测试手段,人工是很难发现bug的,而自动化测试则可以自己跑着,在这期间你就可以去干其他事情了.
5.心得体会
- 经过这次电梯系列的训练,使得我对多线程编程有了更加深刻的理解,首先是线程安全真的是非常重要,但又是最为复杂的东西,对于
wait
和notify
千万不能乱用,盲目的使用一些线程控制语句将会使你的程序变得非常杂乱难以分析,所以一个良好的架构真的非常重要,可以使你的线程逻辑变得非常清晰,这样写起来就会得心应手,不然之后就会越来越困惑,不知道从何下手
- 关于多线程的测试手法也有了很大的理解,最平民化的手法就是
systeam.out.plantln()
但是这个会存在一定的问题,经过向大佬的学习,学会了使用log
来进行debug,还有就是log4j
真的非常好用,当然由于多线程的bug的不可复现性,所以自动化评测手段真的是非常重要.
posted @
2019-04-21 10:42
MioKun
阅读(
303)
评论()
编辑
收藏
举报