第二单元电梯作业总结
一、三次作业的设计总结
第二单元的作业基于电梯的调度,分别为傻瓜电梯,单部可捎带电梯,多部电梯的运行和调度问题,沿袭第一单元求导作业的传统,难度仍然是依次递增,考研设计架构的清晰程度,以及模块化的编程思想。下面分别对三次作业的多线程协同和同步控制方面,对三次作业设计策略进行总结。
第一次作业实现的是单电梯的傻瓜调度问题,主要是适应多线程的编程方式,使用的是生产者消费者模型。在第一次作业中,我的设计是分两个线程,其中主线程负责输入,并将request请求push到任务队列中,开一个电梯线程负责电梯的运行,从任务队列中take一个request,并进行相应的处理。第一次作业的实现较为简单,实现两个线程,并确保requestlist的线程安全即可。在协同和同步方面,requestlist是主线程和电梯线程共同访问的成员,其push和take方法需要加锁保证安全性,以此进行同步,在队列为空的时候,需要进行wait操作,以避免轮询带来的cpu负担。
第二次作业仍然是单部电梯,但是使用的是als捎带策略,其实现方式和第一次作业仍然类似,主线程负责输入,push进requestlist,而elevator线程从requestlist中take请求,区别在于take的选择问题,需要到每一层都进行一次take,且take出的request与als策略的定义有关。通过这种方式可以节省时间,获得更好的性能。其同步和协同与第一次作业类似,不再赘述。
第三次作业难度上升,有三部电梯,每部电梯的运行范围不一致,因此涉及到换乘的问题。仍然考虑模仿前两次作业的设计,主线程输入,三个电梯线程,不同的是三个电梯线程分别维护自己的任务队列,而输入线程首先经过一次拆分,拆分成一次或者两次(即换乘),然后再依据拆分直接push到对应的电梯的任务队列里,至于每个电梯自身的任务队列的take,和上次作业的策略一致,仍然可以选择als捎带策略。在同步方面,每个电梯自身的队列需要与输入线程进行同步,另外还需要注意take时候的电梯不同的容量问题。
总体而言三次作业的架构是一致的,并未进行重构,代码复用率也较高。
二、度量分析
第一次作业
代码规模
第一次作业较简单,行数也比较均衡,属于比较正常的水平。
方法复杂度分析
复杂度也控制较好,并未出现过高的情况。
类图
整体比较清晰,可以很容易的在上面增加功能,并且类和类的分离实现较好。
第二次作业
代码规模
代码量上,电梯线程代码较多,其中有对不同情况的不同处理,表明我对实现的抽象分离仍然不够优秀,还有很多改进的空间,有部分代码过于臃肿。
复杂度分析
从复杂度上看出有部分方法过于复杂,容易使人看晕,事实上在实现的时候过于复杂的方法可读性较差,很难发现bug。
类图
类图与第一次作业的实现类似,都是实现多线程的分离设计交互模式。可以实现代码的复用。
第三次作业
代码规模
在电梯线程中实现代码更加复杂,且到达400行,说明很多实现都不够面向对象,还存在着面向过程的实现思路。
复杂度
复杂度上沿用第二次作业的设计,因此复杂度仍然有部分不够好,且有上升趋势,这表明设计更加复杂,更难抽离出来。
类图
第三次作业的类图较复杂,缺点是设计逐渐模糊,边界不够清晰,对于谁负责什么任务的问题,解答的不够完善。
三、Bug分析
这三次作业我的完成情况较好,正确性较高,在强测与互测中均未出现bug。在实现细节的时候,我采用的是不断进行测试的方式,并对代码进行认真的思考和细节把握,从而最大程度减少bug的产生,在第三次作业的时候,我采用评测机对自己的程序进行400+次随机数据测试,对功能的正确性进行检查。
在第一次作业的时候,我遇到了程序停不下来的问题,对多线程的理解不够深刻,最后采用轮询的方式停止了程序,在第二次作业中采取了wait和notify机制,第三次作业沿用并结合一二两次作业的经验。
四、互测
在本单元作业中,我并未发现其他同学的bug,我的测试工具主要是脚本自动测评,并未人工构造样例进行测试,在测试过程中发现随机数据的弊端在于很难把握边界条件,并不能很好的对特定的bug进行测试,仅仅检查了功能性,因此在未来的测试中需要将两者相结合。
事实上我并未结合对方的架构进行针对性测试,而是采用盲测的模式,这样测试效率低,很难找到针对性的bug。第一单元的测试主要采用的是针对性测试,而第二单元由于增加了与时序相关的概念,需要定时进行投放,仅此很难在输入端进行严密的控制,所以使用命令行窗口进行自动化测评是上策。
五、心得体会
设计安全上,对于共享对象访问的互斥访问,是多线程设计中的重要问题,需要确保自己的变量是安全的,可控的。
设计原则上,不但简化自己设计思路,减少设计难度,增加可分离性,并可以轻松的进行扩展和重用,即为良好的设计。
OO作业进行到现在已经过半,从第一单元求导作业完成情况很差,到现在逐渐熟悉了OO作业的设计模式,以及如何测试自己的代码,以尽可能保证在强测中不出现问题。在不断进步的过程中,我体会到了OO的思想,在朝着写高质量代码的目标奋进,在一次一次的困难和磨练中成长。希望在未来的OO作业中,我可以发扬优势,弥补缺点,努力加油。