北京航空航天大学2019年OO课程第二次总结

电梯作业总结

0.引子

  oo第二单元电梯的作业在此告一段落。从本次作业开始,我们接触了多线程的概念。这是我以前没有接触过的,理解起来比较吃力,增加了本单元的学习难度。线程不安全问题给了我惨痛的教训。

1.设计策略

  电梯第一次作业相对简单,是即使不用多线程,使用单线程也能完成的作业。由于刚刚接触多线程,虽然是比较简单的作业,但是熟悉多线程的知识花了不少时间,因此作业完成的也并不迅速。单电梯的傻瓜电梯并不需要调度,所以没有调度器。第一次作业一共就只有两个线程:一个是读取请求的主线程,一个是电梯线程。有一个安全队列存储主线程取到的请求,电梯线程从安全队列取需要执行的请求,通过安全队列实现同步。

  电梯第二次作业和第一次作业相比,只是多实现了捎带而已。因此我就在第一次作业的基础上实现了捎带。相比第一次作业,主要就是修改了电梯在每一层的行为。电梯在取得主请求以后,就执行主请求(和第一次作业一样,第一次作业的每个请求都是主请求),在每层都要判断,当前楼层是否有要下的人或者同向可捎带的人,有就开门,让想下的人下,让所有人进来。这些都写在一个函数里实现。到这里,已经出现了一个问题。我的这个函数没有严格区分取主请求的人和捎带人,虽然在第二次作业中没有引发问题,却给第三次作业带来了麻烦。

  电梯第三次作业和第二次作业相比,多了两个电梯线程,需要考虑多个电梯之前的协作问题。同时加入了电梯可达层数的限制和电梯载客量的限制。电梯载客量并不是什么大问题,这里不多讨论,但是电梯可达层数就导致出现了一些请求单靠一部电梯是不能够完成的,需要转电梯。虽然指导书指明的架构方法是写一个调度器线程来分发请求,但是我为了复用第二次作业的代码(因为第一单元的作业次次重构,总是有想试试不重构的冲动),决定让三个电梯线程自己分配请求,大体思路就是每个电梯优先取能够直达的请求,其次取没有电梯能直达的请求,都没有则取到null。这个时候,捎带功能就出问题了,会捎带上本电梯无法处理的请求,并卡住。虽然后来修复了,但是从工作量上来说,并不会比重构低。

2.基于度量的代码分析

第一次作业

 

第二次作业

第三次作业

 

优点:三次作业是具有继承关系的,没有重构,通过一次架构,勉强算是实现了可扩展性。

缺点:1.虽然可扩展,但是并没有特意为了拓展设计结构,因此部分代码在拓展的时候代码之间的耦合性偏高,扩展起来并不

   那么容易。

   2.第三次作业线程安全问题没有处理合适,导致程序出现了bug,没有通过强测

3.bug分析

  第一次电梯作业和第二次电梯作业强测都没有出现bug,同时也没有在互测中被hack。第三次电梯作业没有进入互测,所以没有被hack。强测中有十七个点出现了REAL_TIME_LIMIT_EXCEED。同样的问题在中测是就已经出现了,当时定位的问题是:三个电梯线程无法正常退出。涉及到的代码是电梯类的退出部分设计有问题,我的设计必须当所有电梯运行结束以后,主线程(输入线程)取到“null”才能正常退出,没有考虑在电梯运行过程中主线程结束的情况。当时修改以后,能够正常通过中测,自己设计了一些样例也都通过了本地测试,可是没想到测试不够充分,强测出了问题。现在的退出部分设计上没有问题,可能是具体实现有问题,或者是与其他部分起了冲突。从周五强测结果出来以后一直修复bug到周六晚上,没有准确定位到bug位置,尝试的修复都是无效的,周日和周一一直在学习os,截止到写总结的此刻还在修复中,等bug修复有结果了再来更新。

4.debug策略

  一直没有找到十分有效的debug手段,仅限于去阅读他人的代码,来寻找有没有设计上的问题和逻辑上的漏洞,第一次电梯作业十分简单,大家都没有什么bug,第二次电梯作业我所在的房间也没能找出任何bug,第三次电梯作业我没能通过强测进入互测,也就谈不上找其他人的bug。我寻找自己代码的问题和寻找他人bug差不多,都是只能通过检查设计来寻找bug,没有什么行之有效的方法检测多线程安全问题。多线程安全问题比第一单元多项式求导的问题难处理的多,一方面无法重现出现bug的情形,另一方面IDEAdebug的功能也近乎无用,在代码上添加输出语句来判断程序的运行情况是我唯一的debug手段。

  显然,我的这些办法都不够好,如果足够有效,我也不会因为线程安全问题导致十多个点出现了同一个bug——REAL_TIME_LIMIT_EXCEED,最后进不了互测。(第一、第二次电梯作业都试图结合被测程序的代码设计结构来设计测试用例,但是都没有找到bug)

5.心得体会

线程安全:

  写多线程程序时,线程安全是绕不开的。一旦出了bug,发现和修复bug的过程都是十分痛苦的。所以,在写多线程程序时,在设计的时候就应该注意线程安全问题,极力避免出了问题后再来修改的情况。  

  另外,在上一次作业的设计并不优秀,线程安全并不那么清晰的情况下,一定不要偷懒在原代码的基础上进行拓展,不要嫌麻烦,该重构的时候还是得重构。否则,拓展出来的代码丑不说,一旦出现了多线程安全问题,就成了一团乱麻,很难搞清楚。

设计原则:

   降低不同部分代码之间的耦合性。在本单元作业中,我又对这个原则有了新的体会。降低不同部分代码的耦合性有助于梳理代码的结构,有助于代码复用,在修复多线程bug时也能更加清楚地定位到bug的位置。不得不承认,这些以前我以为我菜就能不遵守的原则(过去我认为写出来的程序能用就行,并不追求代码质量),能够提高代码质量,而提高代码质量的目的正是减轻修复bug和进行拓展时的工作量。从下一个单元的作业开始,每一次的作业,我都会尽量提高自己的代码质量,只有这样才能取得进步。

转载于:https://www.cnblogs.com/squidwhite/p/10743369.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值