OO第二单元总结

一、程序设计

​ 本单元的三次作业我没有进行重构,基本上都是在上一次作业的基础上结合该次作业的要求增加功能,进行优化。

​ 第一次作业只有一个电梯,我采用了生产者-消费者模式,Input(输入)线程作为生产者、Elevator线程作为消费者,Controller作为托盘负责接收输入线程的输送请求以及向电梯输入请求,并且有个等待上电梯的waiting队列。电梯类正在电梯内的请求队列。电梯的捎带算法的实现,我是模仿指导书里给出的ALS规则,自己造了个新的方法,增加了一些新的被捎带规则:在某一楼层,只要等待队列里的请求与当前电梯的运行方向相同,便进行捎带,如果有需要,会电梯改变电梯原本的from和to的楼层,这样可以保证每次从waiting队列取出一个主请求,进行捎带,送完一波以后保证电梯里面没有人被锁住。

​ 第二次作业变成了1-5个电梯,并且楼层也有地上有地下,电梯也限制了最多能承载7个人。在这一次作业里,线程之间形成链状生产者-消费者关系。我引入了一个全局调度器,每次输入的请求进入全局调度器,会直接分配给每个电梯,进入该电梯的等待队列,其他的捎带规则和第一次作业是完全一样的,需要判断一下当前电梯的容量有没有满。多个电梯线程结束,只需要每个线程当前输入结束,并且waiting队列和电梯内队列都为空,这个线程就结束,所有线程都结束时,程序就结束了。这次作业的设计我以正确性为主要目标,因为没有进行很大的优化,我采用的电梯调度方法是Input线程输入一个请求到调度器里,首先找到当前没有在运行并且离请求上电梯的楼层最近的电梯,如果没有,就进行摇号,随机分配给一个电梯。

​ 第三次作业比第二次作业的要求更高了:A、B、C三种类型,会在运行中增加电梯,并且每个类型的电梯停靠楼层不同,上一层的时间不同,能承载的人数不同。我依旧是选择电梯一个线程,里面沿用了第二次作业的调度算法,waiting队列和电梯内队列,同时新增了电梯停留时间和承载人数两个变量。

​ 因为电梯停靠楼层不同,所以乘客可能需要换乘,我采用的是动静结合的换成策略,首先用Floyd算法,跑出所有可能请求506种的换乘方法,会发现换乘全部集中在1、5、15楼层。大多数请求并不是只有一种换乘方式,如果直接固定换乘方式,当遇到极端数据时,搞不好可能会超时。因此我在换乘楼层不变的基础上,用了D、E、F、G四种字母分别表示可以搭乘AB、AC、BC、ABC类型的电梯。这样可以记录更多的换乘方法,如果一个请求需要换乘电梯的电梯是F,那么他可以在B、C两个类型的电梯里面找到离他最近或者waiting队列最小的电梯,并把请求加入到该电梯的waiting队列中。

​ 由于输入线程里面读入的PersonRequest所存储的信息过少,因此我新建了RequestP类用于存储,当前请求的id、from、to,以及是否需要换乘、在那一层换乘、换乘前后需要乘坐的电梯类型。电梯的停靠问题只需要保证进入该电梯的请求都是符合电梯停靠要求的就可以,这点在ChangeTable打表时实现了。我画了一个简单的流程图,希望可以描述一个请求从输入到送走的过程。

二、第三次作业分析

​ 由于三次作业是迭代开发的,因此在这里重点分析第三次作业。

度量分析

​ 本单元的作业同上一单元一样,也是有循环复杂度过高的问题,可能是由于在电梯每到一层时,需要遍历一遍电梯的等待队列造成的。ChangeTable是用于存储所有换乘信息的,打表用的是if else,所以也是复杂度比较高。

​ 在功能设计方面,第三次作业也是有一些扩展性的,比如可以新增其他类型的电梯,可以在Elevator线程中新增方法setEle。或者可以使某一个电梯停运,可以使用全局调度器里的setEnd方法等等。

三、BUG分析

​ 本单元作业没有出现线程安全的问题,还是比较令人欣慰的。

第一次作业

​ 在强测中没有发现BUG,互测中hack了别人一次CTLE。

第二次作业

​ 在互测中没有被hack也没有hack到人,但是在强测中出现了RTLE的问题。是由于我在该次作业时,没有用arraylist里面自带的size方法,反而使用自己新建的size变量,导致每取出一个新请求时,从当前电梯楼层now到请求上电梯的楼层to之间,size++了两遍,但是下电梯的时候size--只有一遍。这样会导致电梯本身已经没有人了,但是我用size来判断是否是否还能再上人,数据量一大就会每次只运送主请求。这个BUG非常十分超级特别隐蔽,因为我的电梯捎带是分now->from和from->to两种类型写的,我只有第一个写错了,大多数数据都没有测出来,只是实际运行时间会变多快一倍,所以性能分爆炸。

第三次作业

​ 在强测和互测中均没有找到BUG,也没有找到别人的BUG。在中测和自己底下测试中倒是发现不少手滑BUG以及漏了2层到3层的换乘。

四、心得体会

​ 本单元的作业与上一单元的作业还是有很大的区别的。在第一次作业动手之前也是阅读了很多的资料,再加上周三的实验课进行了代码的编写,才完成初探”多线程“。可能上一个单元自己还是沉浸在面向过程的思维深渊中,这一单元大概更加体会到了什么是OOP,多思考,少重构才是正解。

原文地址:https://www.cnblogs.com/infinite7/p/12708930.html