一、从多线程的协同和同步控制方面,分析和总结自己三次作业来的设计策略及其变化
第五次:这次作业我的策略便是读入指令一个线程、调度器一个线程、电梯三个线程,通过调度器线程将读入指令线程读入的指令分配给三个电梯,而三个电梯则一直在运行,检测是否有指令产生。本次作业完全使用synchronized关键字进行同步控制。
第六次:这次作业因为指导书要求不太明确,我便放弃了读入指令线程这个设计以达到更好地同步控制。我的设计是将指令全部读入后,根据指令数量建立对应的监控线程,这样一来我只需做好监控线程的同步即可,实现起来较为容易。
第七次:这次作业的设计又变回了第五次作业的设计策略,即读入指令一个线程、调度器一个线程来实现指令的读入与分配,之后让100个出租车成为100个线程自由移动。
二、基于度量来分析自己的程序结构
第五次作业:
这次作业因为给电梯分配指令时要考虑的因素过多(例如同质和捎带),因此Dispatch类写的过于臃肿,在分配算法上可以继续优化。
优点:采用Button思路使电梯运行策略变得简单。
缺点:对于捎带判断思路不清晰导致代码变得臃肿。
设计原则缺陷:责任均衡分配原则及懂我原则。
第六次作业:
这次作业由于涉及到线程的类只有Monitor类,导致该类责任过重成为God类。
优点:线程较少,同步控制容易实现。
缺点:Monitor类过于庞大,实现较为复杂。
设计原则缺陷:存在God类,责任分配均衡原则。
第七次作业:
这次因为调度器类只需要让出租车抢单及派单给出租车即可,因此实现较为容易,避免了方法冗余。
优点:各类的职责明确,责任均衡,较好地达成了责任分配均衡原则。
缺点:100个出租车100个线程,稍有不慎便会卡死(例如多层while(true)嵌套)。
设计原则缺陷:局部化原则。Map对象在很多类中重用了。
三、分析自己程序的bug
第五次作业:这次作业因为是第一次接触多线程,对synchronized关键字的用法不太熟练,导致指令读入线程和调度器线程存在同步控制问题(无法正确读取指令序列中的指令),导致其余的设计和实现时间严重不足,遗留了很多bug。本次作业我被发现了4个bug,主要还是电梯运行时时间的处理和同质指令判断。因为我的同质指令判断在调度器中完成,而调度器代码过多,导致考虑很不周全,没有做好ER类型指令的同质判断及存在同质判断输出时间不对的问题。
第六次作业:本次作业被发现了一个在同一文件上实行recover和path-changed触发器后有概率导致找不到文件而crash的bug。这个bug存在的原因是因为在读入指令时该文件存在,但一旦修改文件后,recover会将其改回来,并且导致改名后的文件在path-changed触发器下找不到,而我未想到这种情况,认为读入指令时文件存在便不需考虑文件不存在的问题,因此使用了listfiles方法,但这种情况只能返回null,从而出现了crash。
第七次作业:这次作业被发现了一个时间输出上的错误。主要是我未考虑到出租车的运行需要微小的时间,运行多了自然会产生偏差。
四、分析自己发现别人程序bug所采用的策略
这三次作业均未发现别人bug。策略是按照bug树构造指令。
五、心得体会
这三次多线程作业做完后,我觉得我整个人都上升了一个境界。一是针对大代码量的作业的迅速完成能力的提升,二是针对问题提出设计的能力的提升,三便是不屈不挠的毅力。尤其是多线程电梯作业,因为对多线程完全陌生,导致同步控制完全没做,因此出现了神奇的情况——就算添加指令和分配指令是对同一个指令序列进行的操作,他就是无法正确执行,而是像玩捉迷藏一样偶尔正确执行一次。这真是差点让我放弃,不过后来认真学习了synchronized关键字的用法后,这个问题便迎刃而解了,剩下的只有一个下午以及还没开始写的电梯类(心累),也导致遗留了很多bug。不过熟悉了同步控制方法后,接下来的两次作业我都做得得心应手,也没有被同学挑出来线程安全方面的问题。第六次作业做完我最大的感受便是——都跟你说了要try-catch,因为我过于自信(其实是没想到)自己的逻辑,导致recover触发器的一些问题没有考虑周全,出现了文件不存在的指针错误。第七次作业让我明白了假时间的好处,我在输出出租车运行时间时只是简单地输出了系统时间/100,但没考虑到出租车运行一段时间后会有误差这一问题,导致出现了出租车运行时间间隔为300ms的错误,在稍微用假时间修改后,该问题得以解决。
原文地址:https://www.cnblogs.com/xyt1606/p/8976018.html