OO第二单元总结

一、三次作业设计策略

(1)第一次作业

    第一次作业采用傻瓜式调度,而由于没有性能上的要求,我奇妙的采用了轮询这一简单粗暴这极其错误的方法,虽然顺利的通过了第一次的中测和强测

但也给第二次第三次作业埋下错误的种子,在设计策略上则简单的让电梯线程不断轮询调度器是否有任务,而调度器仅仅是在中间充当一个托盘的功能,

电梯每执行完一个请求则去调度器获取另一个任务,直到调度器读入结束符。

(2)第二次作业

    从第二次作业就开始采坑,首先由于在最开始没有理解清楚禁止的暴力轮询,导致在第一次提交后经过了好几次的修改换成了wait/notify进行线程等待和

唤醒减少了cpu时间,在加入了wait和notify之后,原来对于程序结束的处理自然就出现了一系列的问题。而对于第二次的设计策略,我原本想仿照现实中的

电梯进行伪目的选层电梯进行操作,但后来担心第三次作业会遇到问题于是继而使用了调度器两级消费者模式,调度器是第一层消费者负责获取任务,继而

将任务分发给电梯,电梯按照电梯线程里的进程队列进行运行,但由于反复修改,整个作业早已与最初的想法相差甚远,很多函数耦合性较高,最后在输入

结束分别关闭各个线程产生了更大的问题,并没有等待电梯内部所有指令运行完毕就结束了电梯的运行。

(3)第三次作业

    一次重构累死人,一直重构火葬场。。经历了第二次作业的失败后,我又进行了一波大胆的重构,果不其然。。这次又遇到了问题。这次采用的是单例模

式,调度器作为一个静态类,输入读取到之后在调度器通过调度算法将请求拆分成不同电梯的任务并分别加入调度器中的三个不同的电梯列表,电梯每到达

一层就进行一次任务的获取,如果没有任务就进行等待。这次的问题主要是发生在电梯线程何时等待何时运行的处理上,主要是由于换乘造成的任务分配所

产生的问题当换乘人员没有到达指定楼层后就无法进行其下一个任务的开始,在这个的处理上有很多的小bug最初的设计时并没有考虑到,后来经过debug将

增加了每个任务中的参数,一个是是否有换乘任务,另一个是换乘的下一个任务的地址,用c语言来说也就是下一个任务的指针。

二、基于度量来分析自己的程序结构

(1)第一次作业

(2)第二次作业

(3)第三次作业

 

三、bug分析

三次作业中最主要的bug就是关于线程的暂停和结束以及唤醒,在第一次作业时这个bug问题还不是很严重,但是到了第二次第三次作业就显得很重要了,

线程的退出应该是在输入线程读入到null,结束输入,电梯线程则在调度器任务提取完,输入线程读入null,电梯本身线程内部无任务后结束电梯线程。另

一个问题则是对于换乘与捎带的判读,捎带的判断还稍显容易,只要与主任务方向相同即进行捎带,所以只需要电梯主任务运行方向以及想要捎带的任务

方向进行分析即可完成目标。而换乘则是最容易出现bug的点,不论是换乘任务的生成还是换乘任务获取以及等换乘人员到达换乘楼层后怎么唤醒或者说告

诉调度器可进行换乘,而这其中对于电梯线程的wait/notify都会产生bug,需要有一个精妙的构造避免线程的bug,这是线程运行方面的bug。还有就是线程

安全问题的·bug,在电梯进行获取任务和调度器获取任务对共享电梯任务队列会进行一个访问,因此需要注意加锁。

 

四、debug策略

对于我自己的设计来说,索性没有出现rle方面的bug因为这方面的bug是最难解决的,我一般用两种方法进行debug,其一我写了一个java程序对输出进行分

析,把每个id的电梯乘坐线路进行分析,并打印在一个文件里,这样的话会更直观的发现从哪里出现的bug,通过这个方法你能发现在什么哪一步出的bug,

比如说在出人的途中或者说在到达一个楼层的途中,接下来你就可以进行第二步debug。Print大法好,在上一个方法发现问题之后找到出问题的重点函数,而

且进行一个输出,可以仔细分辨出是哪一个语句出现的问题,之后再输出一系列的任务列表可以通过对任务列表的分析,与你正确结果的差距来分析出问题具

体在哪。当然print大法的弊端在于较为麻烦,所以我在debug的途中在调度器和电梯线程里都写了一个debug方法,即输出当前任务列表里的值,需要时只要

调用这个方法就好。再其次,你就只能通过自己构造测试集发现bug,或者根据强测出现了bug的测试集浓缩其精华,然后构建一个小型的、易于观察的测试集,

然后重复上述步骤应该就足以应付大多数bug了。

 

5.心得体会

线程安全:

  写多线程程序时,线程安全是绕不开的。一旦出了bug,发现和修复bug的过程都是十分痛苦的。所以,在写多线程程序时,在设计的时候就应该注意线程

安全问题,极力避免出了问题后再来修改的情况。而且还应该在开始写代码前仔细思考自己的构造可不可行,是否需要扩展一些功能,不要等到以经开始写代码

的过程中突发奇想进行修改,最后自己给自己制造bug。  

  另外,在上一次作业的设计并不优秀,线程安全并不那么清晰的情况下,一定不要偷懒在原代码的基础上进行拓展,不要嫌麻烦,该重构的时候还是得重构。

否则,拓展出来的代码丑不说,一旦出现了多线程安全问题,就成了一团乱麻,很难搞清楚。当然也不要随意的重构。。真的是耗时耗力,因此最好的方法还是

在第一次作业时就仔细思考可能扩展的功能,预留出这些功能的空间,避免后面每写一次作业就重构一次的惨状再次发生。

   降低不同部分代码之间的耦合性。在本单元作业中,我又对这个原则有了新的体会。降低不同部分代码的耦合性有助于梳理代码的结构,有助于代码复用,

在修复多线程bug时也能更加清楚地定位到bug的位置。能够提高代码质量,而提高代码质量的目的正是减轻修复bug和进行拓展时的工作量。从下一个单元的作

业开始,每一次的作业,我都会尽量提高自己的代码质量,减少自己重构的次数,这样也能不让自己显得如此劳累。当然同时还是存在一些问题,比如说对线程的

操作问题,我现在还仅仅停留在会用wait/notify线程的很多用法还不了解,线程的很多交互方式还并不熟悉,这都是需要在后面继续学习的。

转载于:https://www.cnblogs.com/qj233/p/10758736.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值