OO作业总结第二弹
这个四月,多线程电梯,IFFF文件管理,出租车系列作业之——version1.(鬼知道我经历了什么......)
不用说,三个作业都不是什么省油的灯(白眼)。那先从电梯系列作业终极版——多线程电梯说起吧。
因为之前的电梯程序我写的并不好,在之前的两个版本中我也没对代码做大篇幅的改动,所以各种设计缺陷累积起来,旧的代码怕是扛不住多线程的折腾了,所以我干脆重新架构写了一份全新的多电梯调度作业。大概的设计就是把请求类用继承的方法衍生出了电梯请求和楼层请求这两个子类,似乎比较方便判断和管理;电梯类里面是一个状态机,根据调度器分配给自己的请求队列,自己调度自己运行;调度器这次没给他太大负担,只负责把请求扔给某个电梯就行,调度器不停查询访问请求队列,然后根据电梯目前的运行状态和楼层类的亮灯情况来判断同质或捎带请求,再把请求分配给某个电梯。
我觉得多线程电梯比前两次电梯调度要考虑的逻辑方面的东西要少一些,因为多线程作业使用了Thread类的sleep方法模拟电梯真实运行情况,只要获取实时的电梯状态和亮灯情况就很容易判断请求是否同质,是否可捎带;而之前作业的时间计算完全依赖于逻辑理论分析,写的时候时间计算逻辑很容易出错,这就导致请求判断很容易出错。但是多线程也带来了线程安全问题,哪些对象需要加锁,应该为哪些代码段加锁,都是需要我们慎重考虑的事情。
类图如下:(排了很久,是不是很hin好看!快表扬我!)
下面是metrics:(为了继承上次作业的调度器,我强行把上次作业的包拉了过来)
UML:
可以看出主要是输入判断的函数和电梯类的run函数圈复杂度和块嵌套深度比较大,我把输入判断的条件一块儿写到一个函数里,导致这个函数圈复杂度很高;电梯类是因为run函数里我给写成了一个状态机,且run还得负责调度电梯运行(这似乎减轻了调度器的负担,但同时加重了电梯类的责任)。总的来说这次的代码度量比前几次的电梯作业蓝很多了,感觉这次的修改还是挺成功的。
这次测评并没有被找出bug,对方的话,大概是因为bug树分支太细了吧,由于一个bug导致红了好几个节点,真的很可惜,第一次知道挂上去就撤不下来的我内心很愧疚,还好通过申诉给那位同学撤销了几个,不然我可能会想挖个洞藏起来,不然都不知道如何面对那位同学。
好了,下一个作业。
本来以为结束了多线程OO就可以歇会儿了,看来还是我太年轻。
IFFF,这名字念起来就很烦的样子。这个作业也确实很烦,指导书说的并不清楚,这代表这次作业基本得全靠readme了,这次作业我写的很匆忙,大概是因为电梯写的有些累了,这次对自己也没有什么要求,readme也写的随意,我知道这是不对的,可是当我醒悟的时候已经周三了 :[
这次我用一个监视任务一个线程,每2s做一次快照,存到Info队列里,不得不说把四种监视器合并写到一个类里面真的非常非常。。。繁琐,Trigger写了近350行,修改代码也非常困难,可是当我意识到这一点的时候,已经来不及改了,只好破罐子破摔。。。想了好几天怎么给目录做快照,想了好多方法,但都觉得太繁琐了,最后采用了将监控范围内的所有叶子节点加入到arraylist里,快照只需扫描这个list就行了。
类图如下:
metrics太红了,我就不放了。。。
UML:
因为没有看issue,所以这次因为功能没写全被扣bug挺亏的,rename和path-change之后得继续跟踪文件,其实修改起来就几句话的事情,但因为没写全功能,我觉得测我的同学能帮我测完也是很善良了。以及这次作业存在不少不可复现的bug,因为时间紧迫没有考虑全线程安全问题。
好的下一个。
我又以为熬过了IFFF,OO就过去了,不知道听信了哪位学长的谣言,我并不觉得出租车有多简单噢╰(‵□′)╯还是太年轻。
用一个AlltTaxi线程管理100辆出租车,每隔200ms更新一次状态;每次计算最短路径都调用一次Dijkstra算法,很浪费时间。调度系统每100ms扫描一遍订单list,并广播给所有满足接单条件的出租车,3s后订单管理类处理掉这些被派送的订单或没有缘分坐上出租车的乘客。
类图如下:(gui太多类了图塞不下,就没拉进来)
metrics如下:
UML:
这次被抓出了不少bug,也有很多设计上不完善的地方,非常感谢测试者提出这些问题,还有很多设计在下次作业应该会做一些改动。我测试的同学似乎在信誉度的选择上有一些问题,没什么大问题。
感想:经历过电梯作业,我发现代码可塑性很重要,与其每次都写一份一次性作业不如从第一次开始就好好思考架构方面的问题,提高代码可塑性。于其申诉一些不可复现的问题,不如当初写的时候就避免这种问题的出现。另外,对于多线程程序,线程安全是肥肠重要的一方面,一定要特别注意哪些地方需要加锁,但又不能随意加锁,避免死锁发生。