OO第二次随笔

一、第五次作业

1.类图

  因为这次的电梯要求模拟真实时间运行,而之前我都是通过时间的运算来判断同质捎带的,所以之前的电梯的调度就不能用了,这次基本就是完全重写了一个电梯。从类图来看,各个类的分配还是比较均衡的,但是我的状态都是用的数字来表示,不符合显示原则,代码的设计风格也不是特别好。

2.度量

 

度量上看,我的圈复杂度和嵌套深度日常红,看来我得好好研究一下怎样才能不嵌套那么深了。。

3.sequence diagram

4.分析

(1)在线程的设计上

  本次作业一共设置了ReqSimulator、ElvRun(*3)、MultiScheduler五个线程,ReqSimulator与MultiScheduler共享一个托盘RequestMonitor,ElvRun与MultiScheduler共享三个电梯。ReqSimulator负责接收输入的请求,将一行请求放入共享托盘RequestMonitor,而MultiScheduler中存有所有待处理的请求(sharedReqQueue),调度器不断的负责扫描该请求队列,如果有可以执行的请求就将该请求从队列中取出分配给相应的电梯。MultiScheduler每次扫描前,尝试从RequestMonitor中取输入的请求,如果有就一次取出来放入该请求队列中。在线程同步的问题上,因为RequestMonitor不能同时放和取因此要给他的方法加上锁。同时MultiScheduler和Elevator共享一个灯(Floor类和Elevator类中的灯),所以灯的按亮和暗灭也是不可以同时进行的,所以Floor类和Elevator类中的相关方法也要加上锁。

   因为MultiScheduler需要访问Elevator的属性,害怕如果Elevator是线程的话会有啥问题,所以不把Elevator作为线程而是又写了一个EleRun线程来管理电梯的运动,MultiScheduler和EleRun共享Elevator。ElvRun通过读取电梯的状态,控制电梯运行的方向,并不对电梯的状态做出更改,而MultiScheduler也读取电梯的状态,根据电梯状态给电梯分配主请求或更换主请求或分配捎带请求。

(2)bug分析

  本次作业中存在的一个问题就是在MultiScheduler中没有给电梯的状态照快照,根据快照来判断请求的分配,这样的话程序运行可能会有误差。这次测试挂了一个公测的bug,那就是关于多台可捎带电梯按累计运动量选取时有一些小问题,导致挂了一个公测。

  我分配到的作业只有非法输入才会在文件中输出,但是合法输入貌似不会响应,文件中没有任何输出,所以公测中除了非法输入的样例以外其他都无法通过。

二、第六次作业

1.类图

   

  从类图看,这次将四个触发器放在Monitor类里,Monitor类中通过判断触发器类型选择执行哪个触发器,并且一个Monitor中可能有好几个任务,所以Monitor判断触发条件成立了,要执行三个if判断来完成相应的任务,这样的话Monitor中的代码比较复杂而且冗余,不符合单一职责的设计原则。

2.度量

 

 

我的圈复杂度和嵌套深度还是很红,大概很大一部分原因就是我的Monitor的设计太冗余了吧。

3.sequence diagram

4.分析

(1)在线程的设计上

  本次作业根据触发器来开线程,由一个监控目标和一个触发器类型来唯一的确定一个线程。在监控线程中,存有监控范围上一状态的快照,并且在每次循环sleep完后取一次监控范围此时的快照,每次根据新旧快照的变化来判断是否触发,并在判断完更新监控范围旧快照和监控目标的快照。因为java提供的File类并不是线程安全的所以我将File类封装成了SafeFile类(然鹅封装的也不是很好)。同时SafeFile类的属性存的是监控目标的快照,每次判断结束就调用SafeFile类里的update方法来更新那些属性。因为Monitor类中不是随时都要访问SafeFile类的属性,只是在开始判断前需要取快照,所以关于线程安全的问题并没有那么多,只需要在SafeFile类里上锁就可以了。但是在组织快照上,因为我不会用树,也不是很懂java提供的一些很好用的工具,我只能用arrayList来存储快照,这就使得我的程序效率不是很高。

(2)bug分析

  在开始写这次作业之前,我本来以为这次作业会比上次好写,后来发现是我太天真,上次作业好歹有个清明假期可以研究咋写,这次作业我在周一晚上还处于一筹莫展没有写完的状态儿,导致儿我一度十分绝望曾经在放弃的边缘试探,好在后来我坚强的收回了脚把它写完了。但是因为测试的时间不够,我还是有一些bug的,因为监控目标是目录的情况我没怎么测试,导致我有一个与目录相关的大bug没有发现,直接影响了我监控目标为目录的大部分功能儿,挂了不少bug。

  本次作业拿到的代码设计的很清晰,我没有找到bug。

三、第七次作业

1.类图

 

   这次作业中特别注意了类的规划,各个类的职责规划的比较清晰了,Taxi中放了一个状态机来控制它的运动,Scheduler负责扫描请求队列,为请求进行派单和抢单,TaxiSys在完成初始化之后就负责读入请求,将合法请求加入到Scheduler中。设计原则上,出租车的状态时用了四个常数(private static final int),没有用enum所以不符合显示原则,因为出租车是通过状态机来控制运动的,可能run方法比较冗余,但是我想不到什么更好的方法来控制它运动了。

2.度量

 

 

3.sequence diagram

 

4.分析

(1)在线程设计上

  本次作业有Taxi(*100)、Scheduler、TaxiSys一共102个线程,TaxiSys和Scheduler共享一个RequestQueue,TaxiSys接收输入的请求并放入请求队列中,Scheduler每次循环如果请求队列非空则先访问请求队列的对头,如果请求队列的对头的抢单窗口应该关闭则将请求从队列中取出为他派单下一次再判断队列头,直到队列为空或者没有应该派单的请求,然后再为请求队列中的所有请求抢单。在线程安全上,TaxiSys和Scheduler共享一个请求队列,因此请求队列中必须加上锁,限制不能同时放或者取。而Scheduler每次需要用出租车的状态来判断时,都需要找出租车的快照用快照来判断,而不是直接访问出租车的状态,避免出现误差。

(2)bug分析

   本次的程序有一个小bug,就是在为请求派单时获取出租车到乘客处的最短距离时,如果两点的坐标一样,,得到的最短路径长度不是0,最后找到我的dijkstra函数返回最短路径长度的时候有一个地方写错了数组下标(真让人老脸一红)。

  本次作业拿到的同学的代码没有找到bug。

四、总结

 (1)初次接触多线程真的是超级痛苦了,测试的时候老发现一些让我老脸一红的bug(内心还老觉得就是多线程的锅)。这种时候,我认为需要先疯狂输出来判断一下到底是判断条件除了问题还是线程同步上出了问题。

(2)找bug的策略基本就是按照bug分支树来找,尤其越到后面越不好测试,只能是按照分支树结合测试线程查看状态来测试。

(3)初次接触多线程,对于多线程的同步我还是只会简答粗暴的在方法前面加synchronized。虽然这样可能会影响程序的执行效率,但是因为我能力有限,没有尝试lock等机制,现在就只会用synchronized了。

(4)感觉自己现在写代码前想的东西明显变多了,先要读指导书然后思考应该怎么规划,涉及的线程安全问题又是什么,也会和同学舍友一起讨论,想清楚之后才会开始写。写的时候也会把能重用的东西抽象成一个函数,减少代码的冗余。但是关于设计风格和设计原则方面的问题还是存在,自己还是需要不断改进。

猜你喜欢

转载自www.cnblogs.com/zzpp2333/p/8971352.html