OO游记之四月篇

第五次作业--多线程电梯

1.设计策略

  本次多线程电梯作业对之前从未接触过多线程的我们是一个不小的挑战,多线程之间数据的共享,成为了学习过程中最大的障碍。

  在我本次作业的架构中,调度器和输入部分共享一个请求队列,三部电梯各自和调度器共享一个小请求队列,对于队列的操作都要通过synchronized获取锁来进行,保证对队列的操作都是原子操作,不会被中断,从而实现线程的同步控制和对共享对象的保护。线程之间的协同使用了wait+notify的方法,当调度器线程扫描完一遍队列之后就会进入wait状态,直到电梯状态改变或有新的请求加入队列才会被notify,避免了高频重复遍历队列导致的CPU占用资源过多的问题,保证了效率与安全。

2.程序分析

(1)度量分析

 

  本次多线程电梯调度情况较为复杂,导致if-else出现过多,并且嵌套过深,代码有些臃肿,需要改进。

(2)类图

 

  本次作业类的设计沿袭了之前单线程的架构,InputHandler类进行处理; Request类为请求;RequesetQueue类为请求队列,由于该队列为共享对象,对于队列中的方法加上了synchronized进行同步控制;Scheduler类为调度器,用于分配请求;Elevator类为电梯实体,模拟电梯的运动并执行请求。

(3)时序图

  本次作业共有五个线程,包括输入线程、调度器线程和三个电梯线程,新的请求通过输入线程传入调度器中,调度器根据电梯运行情况分配給三个电梯线程中的一个,电梯在收到请求后进行运动,从而完成功能。

(4)设计原则

  本次的设计中Scheduler类完成了较多部分的工作,有悖于责任均衡分配原则。

3.BUG攻防

  本次的Debug工作主要耗费在了共享对象的保护上,synchronized的添加也是耗时很久才基本理解其方法,但是还是出现了纰漏。由于一个地方未进行保护,被测试者找出了一个因为数组越界而产生的Crash,实在是不应该。同时,由于JVM调度的问题,在一些临界情况的处理上出现了不确定性,从而产生了bug,而这一点的优化较难,至今未得其法。

  在这次别人代码的过程中,还是按照以前的路数,先用自己debug过程中的测试数据进行测试,很容易就发现了对方一些处理不得当的地方,进而读了代码,找出一些逻辑漏洞,构造样例进行测试,很容易的找出了一点bug。

第六次作业--IFTTT

1.设计策略

  这次作业在设计阶段就进行了权衡,可以以触发器为线程进行构造,也可以以每个监控任务为线程进行构造,想了一下,为了保证每个监控任务都能快速准确响应,采用了一个监控任务一个线程的架构,这样的方式简洁明了。在每个监控任务中,不断重复的扫描对应的目录或文件,检测文件相应的变化,实现监控。同时,设计了SafeFile类的同步锁,保证在对文件访问与修改时是线程安全的。

2.程序分析

(1)度量分析

  原因同上次一样,任务较为复杂,简化起来很困难。

(2)类图

  本次的设计较为清晰,InputHandler进行输入处理,将请求加入到RequestQueue队列中;Request类用于存储请求信息;Trigger为触发器,根据不同的请求构造出不同种类的触发器进行监控;SafeFile类为线程安全的文件系统;Summary和Detail类为依据指导书要求设立的记录单元;TestThread为测试线程,用于进行文件操作。  

(3)时序图

  本次作业共有三种线程,一个Smmary线程用于记录触发器触发次数,一个Detail线程用于记录触发信息,还有Trigger线程,根据每个监控任务构造一个触发器监视相应的变化。整个流程为输入所有的监控任务后,为每个监控任务设立一个线程,在检测到变化之后进行记录或撤回操作。

(4)设计原则

  本次作业中未将触发器分成四种,而是在一个触发器中写了四个不同的函数,有些违背了责任均衡原则。

3.BUG攻防

  本次作业虽然写的时候很迷,但是在基本功能实现之后,就没有进行过多的改动,利用测试线程测试了所有的基本情况没有出现什么问题。但是在互测中还是被找出了bug,原因是在线程初始化的时候,由于测试线程未设置缓冲,导致如果在最开始时测试线程修改文件名,就会检测不到变化,是自己欠缺考虑了。

  互测时拿到了一份很工整的代码,思路清晰,风格良好,只是由于疏忽输出错了一点东西,没有功能上的bug。

第七次作业--多线程出租车

1.设计策略

  本次的设计有些类似于多线程电梯,调度器和输入部分共享请求队列,调度器再将队列中的请求按照规则进行分配。不同的是,为了防止100个线程对系统资源不可控的抢占,只为出租车开了一个出租车群线程,在这个线程中对100辆出租车进行轮询,得到出租车更新的信息之后进行派单。

2.程序分析

(1)度量分析

 

  同上一次作业一样,可能是因为情况太复杂而自己并没有优化,导致这个问题一直没有被解决。

(2)类图

 

  本次作业的类图稍显凌乱,InputHandler类、Request类、RequestQueue类的作用和之前类似;调度器类通过出租车群管理出租车,进行请求分配。

(3)时序图

 

  本次作业共设计了三个线程,一个输入线程,一个调度器线程,一个管理100辆出租车的线程。输入请求后加入调度器的请求队列,调度器不断扫描队列,根据出租车的位置、状态等信息进行分配。出租车在接到单之后会切换状态,并将每时每刻的信息返回给调度器。

(4)设计原则

  本次在设计时进行了较为充分的考虑,个人认为基本符合了要求原则。

3.BUG攻防

  本次作业的测试难度较高,在完成正常功能后,对容易出现的问题通过输出进行了查看,功能方面没出什么问题。但在互测的过程中被报了使用假时间延迟的bug,这是设计层面的缺陷,可以通过修改sleep的时间来进行调整。

  在互测的过程中,查到了对方出租车在运动的过程中运动间隔不是200ms的bug,这是由于代码执行过程中的延迟造成的。

心得体会

1.多线程程序的bug十分难调,并且有时候还不容易复现,因此为了避免出现”代码五分钟,bug两小时”的情况,还是从设计时候开始就认认真真对待,稳扎稳打吧。

2.多线程安全问题很重要,有时候一忽视就会出问题。

3.设计原则很虚也很实,一份好的代码是可以让测试者心情愉悦的。

4.不要相信”下一次就轻松了”这种话

5.OOOOOOOOOOOOOOO

猜你喜欢

转载自www.cnblogs.com/blackpineapple/p/8977610.html