作者:LYJ189_163 | 来源:互联网 | 2023-08-16 10:56
本文由编程笔记#小编为大家整理,主要介绍了OO第二单元单元总结相关的知识,希望对你有一定的参考价值。
总述
OO的第二单元主题是电梯调度,与第一单元注重对数据的输入输出的处理、性能的优化不同,第二单元的重心更多的是在线程安全与线程通信上。这此次单元实验之前,我并未对线程有过了解,更谈不上“使用经验”,整体上第二单元三个实验也做的较为吃力。三次实验,也算是对线程的一步步入门吧,以及由于对于线程不是很熟悉,所以我总是下意识的把程序分割,尽量减少通信量。
第一次实验
基本需求:单电梯、无捎带要求、基本无性能要求。
基本实现:一个主线程或者一个主线程与一个电梯线程
我采用的方法是使用一个主线程,因为实际上,对于第一个实验唯一让人认为要使用线程的地方可能就是模拟电梯上下层所需要的时间了,但是事实上我们可以通过让主线程sleep的方式来完成此功能。以下是相关类图....
总结:第一次实验是入门的铺垫,对于线程相关要求很低,对于我而言,可以说是给予了一定的缓存时间来完成两个之间单元的切换。
第二次实验
基本需求:单电梯、傻瓜式捎带。
基本实现:多线程
第二次实验与第一次实验最大的不同在于,由于存在捎带也就有了一定的性能要求,故而很难去用一个主线程去做。事实上,我认为如果牺牲性能,就第二单元的电梯调度而言,是可以用一个主线程去模拟的。一个显而易见的做法就是一次只乘一个人。不过这又是另外的事情了。话说回来,第二次实验我采用的方法是,一个主线程负责接收请求,一个电梯线程负责模拟电梯的运行以及内部自行调度。
说到调度,由于电梯运行是一个在线问题,关于调度的优化算法很难去证明是否有效(严格证明优化算法的期望性能是一件很难的事情),即使做出了期望性能优秀的算法,还有可能会因为数据的边界性而表现糟糕。总的而言,就是很难优化,优化了之后也不见得有什么用。基于以上思想,对于调度算法,我的实现并不复杂,基本是按照指导书的傻瓜式捎带而写成的。
这里值得一提的是,采用贪心可能有一定效果,不过最终还是看脸,至于其他的许多算法感觉都是在面向个例优化(这里只是个人感觉,无其他任何意思)。以下是第二次电梯的相关类图
总结:从日常交流来看,第二次实验有许多大佬花了很多时间在做相关调度优化。而我由于实力有限,把重心主要放在了对线程的安全、线程的通信控制上面,我的理念是降低耦合,降低结构复杂度,能不锁就不锁,能自己分析清楚的,就不交给安全机制来写。
第三次实验
基本需求:多电梯多楼层、捎带换乘,有一定性能的要求。
基本实现:多线程
第三次实验在第二次的基础上,增加了电梯的数量,并且每一个电梯有了自己的容量、区间、运行时间等等信息。并且在这种情况下,对程序的性能提出了要求。我采用的方法与第二次实验类似使用一个主线程处理请求,另外设置一个电梯线程来负责调度。之所以这样做,一方面是自己懒惰了,另一方面也是过于相信自己的码力了,到最后才发现自己驾驭不了。以下是第三次实验的类图。
总结:第三次实验我的强测分没有及格,究其原因一方面是没有进行有效的对拍测试,一方面是过于注重对于线程安全方面的考量而忽略了程序本身的业务逻辑。不过这也是由于缺乏信心,多线程还是接触的少了,总是担心会出现各种线程安全的问题。
Bug分析及相关测试策略
三次实验我都没有去测试其他同学,主要是因为多线程本身的不确定性,以及对于多线程很难去对拍测试实现自动化,又不想用其他人的。所以最后结果就是自己被测爆了。不过私下交流主流的测试策略应该都是实现自动化,然后随机数据跑,判断结果的正确性就按照指导书的正确性判断思路。
在第三次实验,我在强测中出现了bug,在互测中也被同学发现了bug,具体bug原因是因为我的调度逻辑考虑的不周全,具体情况是,在某些情况下,一个电梯可能会在同一个楼层反复接一个人,这虽然只是影响性能,但是由于我的设计中压根没有想到有这种情况发生,所以导致了我的电梯会出现连续arrive同一层的错误输出。修改起来还是挺方便的,对于arrive的输出判断一下就行了。
心得体会:
线程安全总是会纠结“加不加锁”、“加几个锁”,“加多了结构复杂怎么办”等等问题,我在三次实验中对于线程安全的处理总原则就是,能不加就不加,能不写锁就不写锁,能降耦合就降耦合。
这样做的好处就是程序的结构不会看起来特别的复杂、零乱,坏处就是对于一些隐式的线程安全问题的分析,需要考虑全面,否则容易造成死锁等等。
有得有失吧,其实有时候程序的结构复杂一点,也只是编码上繁琐 一点吧,实现上还是挺方便的,这一点仁者见仁,智者见智吧。