欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

OO第二单元总结

程序员文章站 2022-04-28 15:58:28
这一单元作业是围绕电梯调度进行展开,并引进了多线程的概念。与第一次作业比较类似,作业难度也是逐渐推进,从最开始的单部电梯先来先服务(傻瓜式调度),到之后的单部电梯可稍带调度,到最后的多部电梯分楼层调度。下面分别说明并分析一下三次作业的设计结构。 第一次作业 作业概述:程序的输入流会不定时随机投放若干 ......

这一单元作业是围绕电梯调度进行展开,并引进了多线程的概念。与第一次作业比较类似,作业难度也是逐渐推进,从最开始的单部电梯先来先服务(傻瓜式调度),到之后的单部电梯可稍带调度,到最后的多部电梯分楼层调度。下面分别说明并分析一下三次作业的设计结构。

第一次作业

作业概述:程序的输入流会不定时随机投放若干用户请求,用户的请求包括出发楼层和目标楼层,电梯没有容量限额,在规定时间上内完成所有请求。

这次作业的意图是让大家对线程有一个初步的认识(因为用户请求不定时投放,电梯强制在线必须要用线程才能搞定),共享对象的加锁保护以及线程之间的同步控制。单论本次作业的难度还是很低的,我大概用了三四个小时就完成了本次作业。

设计策略

由于第一次作业只有正确性要求,没有性能分,所以我也就没费工夫想如何优化调度hhh,就直接写了个先来先服务的模型。尽管电梯很愚蠢,看着有人经过也不捎带一下。。。但是在正确性上有十分充足的保证。

实际上,第一次作业得电梯调度就是最经典得生产者消费者模型,整个代码也就分为了三个部分,两个线程。主线程也就是第一部分用来接收用户请求,也就是生产者,另一部分是共享对象用来存储请求队列,最后一部分是电梯线程用来从请求队列中获取请求,也就是消费者。

代码分析

设计图

OO第二单元总结

各个类得作用请见设计策略。也没什么可具体分析的了。

度量分析

OO第二单元总结

OO第二单元总结

可以看出这次设计的层次还算不错,各个指标都没有特别高的。当然这是因为这次作业比较简单。

bug分析

分析自己程序的bug: 这次作业没有bug。
分析他人程序的bug: 高工这块没有互测部分,但是也和同学私下互相讨论过,测试方法就是写几个测试样例看看结果是否正确,以及看看代码内部是否有明显的逻辑漏洞。均为发现错误。

第二次作业

作业概述:这次作业和第一次作业基本一样,也是一部电梯,同时没有人数限制。唯一的区别就是要完成捎带调度。当然说是增加了调度算法,但是实现起来还是十分容易的。只需要每次到达一层楼的时候看一眼该楼层是否存在相同运行方向的等待的人。

设计策略

基本和第一次作业一样,同样都是两个线程,分别是主线程读取用户请求,子线程运行电梯。共享队列实际上是内置在电梯中的,但是为了方便理解,我还是单独写了一个共享队列的类,但是并没有做成线程,只是经了一下手立马就发给了电梯的内置队列(自己骗自己hhh)

代码分析

设计图

OO第二单元总结

度量分析

OO第二单元总结

OO第二单元总结

bug分析

分析自己程序的bug:似乎还是没有bug。。。这次虽然还是没有bug,但是因为有了性能分,所以并不是满分。我也只是实现了指导书中推荐的捎带算法,没有考虑其他更好的优化方法。实在是打不过优化大佬们。。。
分析他人程序的bug:在和其他小伙伴交流的时候还是没有发现什么bug,有的同学是把所有请求都添加到电梯中,也就是不管这个人是向上走还是向下走,你先进来,先和我绕一圈回头我再送你去你的楼层。虽然很不符合实际,但是似乎比常规的捎带方法最终的时间还要短。。也是有点意思。

第三次作业

作业概述:这次作业有了很大的升级,分为了三个电梯,每个电梯可以停留的楼层还不一样,有的人还必须要换乘才能到达指定的楼层。各个电梯的速度也不一样。

设计策略

这次的设计结构不同于上述两次作业,要复杂很多。由于这个有三个电梯也就是有多个消费者,所以并不能像之前那样把共享对象写在电梯里面,而是要有一个调度器对所用请求指定电梯后,在电梯内部再进行二次调度,也就是可稍带调度。所以总体上是有五个线程,一个主线程接收请求,一个子线程作为主控用来处理请求队列的分发,剩下三个是电梯线程,用来处理每个电梯的调度以及电梯的运行。但实际上由于这里有的请求非常的麻烦,需要不同电梯协同工作才能完成,比如说请求要从20->3楼,而只有a电梯能停留20楼,只有c电梯能停留3楼。所以这种情况我的处理办法是先让a电梯停留在一个ac都能停留的楼层,比如说5楼,然后这时把请求发到5楼同时修改成一个新的请求为5->3楼,这样再把这个新的请求发送给主控的共享队列。也就是说除了main线程是生产者以外,电梯内部也可以生产新的请求。至于是如何调度的,我的调度器十分简单,就是先判断是否有直达电梯,并将请求发给最近的直达电梯。如果没有可用的直达电梯(两种情况,直达满了,或者就是需要中转的)就给一个最近的电梯。电梯到每一层的运输规则都是写死的,比如如果能直达就直达就ok了,但像a电梯不能到3楼,所有通过a想去3楼的就都会送到5楼。显而易见,我这种方式绝对不优,甚至有时候很愚蠢。

代码分析

设计图

OO第二单元总结

度量分析

OO第二单元总结

OO第二单元总结

OO第二单元总结

可见request类的sendrequest()函数的度量值很高,这是因为里面进行了非常对的if判断,来分类到底要给哪个电梯。

bug分析

分析自己程序的bug:依旧没有bug。
分析他人程序的bug:我看的大多数小伙伴的代码bug主要集中在程序结束判断上。当然不同人写法不一样,但大体来讲不能简单通过main线程的输入结束来判断是否要关闭主控线程,必须要等所有的电梯都结束了同时没有输入了才能关闭。

总结

先从课程作业体验上讲一下,总体感觉这一单元的体验要比上一单元好一些,代码写得也顺利很多,最多用一天就都能写完(难道是我进步了???)。
在说说多线程编程的体会吧,总的来讲前两次作业不需要太多的思考,简单加个同步锁就ok了。但是在第三次就了一些更深的感受,首先多线程debug就很不同,单步调试基本没啥用,print会更直接。其次就是加锁的艺术,有的时候全部加上锁肯定没问题,但是性能会下降很多,但是如果减少锁的范围可能又会出现不同步带来的bug,所以需要好好权衡和设计这块。

最后感谢老师和助教的帮助和指导!