OO第二单元总结
面向对象第二单元总结
背景
面向对象第二单元的主体内容是多线程及线程安全的知识,其中穿插了面向对象的集中设计模式:单例模式、观察者模式、Worker Thread 模式。在第三周,我的身体状况未能支持我写完第三次电梯,所以我感到十分抱歉。
一.设计策略
-
第一次电梯:类似于生产者消费者模型,把请求队列作为托盘(共享对象),生产者的行为是人发出请求,消费者的行为是电梯处理请求,电梯每次从请求队列中取出一个请求进行处理。这种调度算法一次只能运送一个人,不能捎带,性能极低。
-
第二次电梯:采用look算法,一次扫描和处理一个方向的请求,当电梯处理完请求后运行前方没有请求时,立即调转方向处理另一方向的请求。我设置了分楼层的19个等待队列和电梯中正在处理的乘客信息队列。
-
第三次电梯:我的设想为:设置一个主请求队列和三个电梯私有请求队列。先将所有请求归并到主请求队列中,主请求队列判断是否能由一部电梯送达,可以的话交由那一步电梯处理。若需要多部电梯协作,分析可得所有请求都可以拆成至多两个请求即可,那么可以在第一部电梯中扫描该楼层是否为第二部电梯的有效范围,若是则下乘客,添加请求到该楼层的请求队列中去。
几次有效作业我均未设置调度器这一概念,电梯的所有行为都由其内部自行处理。第三次作业中的主请求队列承担了调度器的部分任务。
共享对象的维护我采用了
wait()
,notifyAll()
的方式。当队列为空时wait()
,当有信息传入时唤醒线程。
二.程序结构
1.第一次电梯作业
-
类图
-
时序图
-
-
度量分析
-
ev(G):核心圈复杂度。
iv(G):方法设计复杂度。
v(G):圈复杂度。
-
设计原则
-
Single Responsibility Principle:基本符合单一职责原则。
-
Open Close Principle:扩展性不强,缺少调度器。
-
-
总体评估
第一次电梯的要求是一个一个处理请求,所以没有什么难度,架构简单,耦合度也低。但是程序拓展性不好。
2. 第二次电梯作业
-
类图
-
时序图
-
-
度量分析
-
-
-
设计原则
-
Single Responsibility Principle:基本符合单一职责原则。
-
Open Close Principle:电梯可扩展性强,但仅支持单请求队列,拓展后的电梯性能较低。
-
-
总体评估
本次电梯作业采用LOOK算法,当有指令发出,立即存到对应楼层的上行或下行请求队列中,每次电梯达到一个楼层时,就扫描该楼层运行方向上的乘客。这是模拟现实电梯的调度算法,其本身还有有一定的优化空间。比如可以在运行时判断此时稍近的最远楼层然后调转方向。
3. 第三次电梯作业
由于本次作业未完成,本人仅绘制时序图已表现我的思路。
-
时序图
-
-
分析思路
设置一个主请求队列和三个电梯私有请求队列。先将所有请求归并到主请求队列中,主请求队列判断是否能由一部电梯送达,可以的话交由那一步电梯处理。若需要多部电梯协作,分析可得所有请求都可以拆成至多两个请求即可,那么可以在第一部电梯中扫描该楼层是否为第二部电梯的有效范围,若是则下乘客,添加请求到该楼层的请求队列中去。
三.程序BUG
BUG可能出现的场景:
-
在判断逻辑上。比如使用LOOK算法时判断电梯是否转换方向
-
在线程安全上。就第一次电梯作业来说bug很难出现,第二次电梯作业可能在线程安全上会出现问题,但是这种问题出现的概率不高,同一组测试数据可能要运行10次左右才会复现,这时候应该保存好数据好好分析。
线程安全bug分类
-
没处理完全部请求就结束
-
线程结束时间不对或者延迟过多
-
-
在优化时。有可能在优化时考虑不周,或者优化导致原本不会出错的出错了。
Debug策略
-
随机数据测试
-
关键点覆盖测试
四.Hack策略
编写测评机,但是测评机不够强大,如果电梯内留人或者电梯有些指令没有处理或者电梯没有输出,测评机都无法识别。在编程的时候本人也记录了几组容易出错的数据,但都没有hack成功。
五.心得体会
这个单元学的不是非常透彻,在完成作业的时候也没有用上多线程的更多知识,我还需要花些时间去理解和运用多线程。还有就是设计原则的问题,设计原则要求单一职责原则和开闭原则,开闭原则我也花了些时间构思,但是构思的结果和事实出现的第三次作业要求相去甚远;单一职责原则这一点我做的不够好,我两次作业只有三个类,一个主类,一个数据结构类和一个电梯类,其中数据结构类充当楼层类的作用,电梯类充当电梯和调度器的作用,导致电梯类的代码十分冗长。