第二单元总结
第一次作业
思路与反思
第一次作业只有一部电梯,简单地用look算法,电梯在楼层间不停来回,遇人则上,放人则下,若上行时楼上无进出则更改方向,下行同理,用Cnt记录已完成的请求次数,用布尔值In表示输入完成与否,以二者作为电梯停止的标志。多线程体现在电梯线程与请求输入线程的交互上,与之前面向对象遇到的问题不同,输入的请求不会在一开始直接输入完毕,而是在线输入。
UML类图
度量分析
耦合度
第二次作业
思路
第二次作业与第一次的迭代在于电梯增加、人数限制、楼层改变,我依旧用的look算法,在第一次作业的基础上修改细节即可,多部电梯要求实现线程安全,由于我使用的look算法,电梯盲目运行,没有更高级的调度,只需要在电梯开关门期间利用synchronized阻塞调度器,使用其中的共享变量来工作即可,五部电梯*抢人。调度器中存储了例如每层需要进入的人员、需要出电梯的人员、进入过电梯的人员等,使得电梯带人方便自如。
UML类图
度量分析
耦合度
第三次作业
思路
第三次作业的新内容主要为电梯类型的多样和加入电梯的请求,电梯类型不同使得电梯可停靠楼层、转移时间、最大载客量,根据可停靠楼层来分析直达与转乘,依旧使用的是look算法,将1楼作为换乘站,将电梯的特征属性作为电梯类的通用属性,根据类型的不同给予不同的初值即可,与第二次作业类似,请求的完成时修改Cnt必须是乘客到达目的地而非转乘处,整个迭代过程并不困难,但是这种调度的性能极差,电梯一直在工作,十分费电。
UML类图
度量分析
耦合度
程序bug分析
第一次作业强测bug是由于性能过低,将scan算法改为look算法即可
第二次作业强测bug是由于没注意到16层,过于粗心
第三次作业强测WA两个点,都是性能过低导致的,并且这些测试点都在极限时间边缘疯狂试探,有时这个点过了另外超时一个新点,可能这就是多线程的魅力吧。互测被hack一次稍微修改调度提升性能后直接修复了,这个bug我无法复现,感到十分迷惑......
前两次作业都不小心使电梯在最初Arrive时输出了Arrive1层,导致出现电梯原地TP的bug,在控制输入请求时也经常出现问题,比如无法结束、两个缓冲区、第三次作业两种请求的分辨等。
寻找bug的策略
利用无时间戳的数据找bug,由于自己程序算法十分简单,bug多出现在条件控制跳出循环和细节处理上,我并没有遇到很多多线程的线程安全问题,而对于这些能够复现的bug,从输出中很容易观察出来问题所在。在寻找其他人的bug时,多用了自己曾经错过的样例。
可拓展性
第三次作业虽然在电梯类型上稍作考量,使电梯的属性更加抽象,但是给每个电梯A、B、C都写了一个运行方法,并且根据type的不同在run方法中调用不同的电梯运行方法,这样导致每次增加电梯的类型都需要新增运行方法。并且回头看,这些方法的不同之处仅仅是根据不同的可停靠楼层来判断到达楼层是否开门,绝大部分代码是复制粘贴的,因此这些方法完全可以封装在run方法中。在迭代的过程中,没有仔细思考程序的鲁棒性,在调度器中有信息的存储,在电梯类中也有很多信息的存储,只考虑了编程过程的方便。电梯中一些数组如存储通过A类电梯可直达的请求也可以存在调度器中,这些不考虑设计的迭代将电梯本身也限制到调度器的一部分中。
心得体会
多线程是面向对象的全新版本,在接触多线程初期遇到很多不可描述的问题,让我感到十分灰心,但是自从我遇到了look算法,让我从谷底看见了翻身的机会,虽然我在这个单元的学习中几乎在只追求正确性心理下完成了三次作业,但我觉得学习的过程还是很充实的。这个单元的遗憾就是处理多线程我居然只是使用了synchronized来阻塞和sleep来睡觉,一个wait和notify都冇,性能分低的可怜,过程性的编程还随处可见。这次通过讨论区的学习以及向同学求助解决了输入请求的两个缓冲区的问题,在交流过程中谈及我的离谱做法虽然低性能但是似乎很有趣,在交流过程中也体会到了一起学习的乐趣。这个单元我没有重构,所以我没有死亡,但是真的很咸鱼,希望我下个单元能翻一翻,但尽量别写bug。求求了。