2019OO第二单元总结

(1)设计策略

电梯第1次作业是一个傻瓜调度电梯,使用先来先服务原则,不用考虑捎带(可以认为电梯的载客量为1),因此比较简单,调度器用一个队列就可以。

使用生产者-消费者模型,输入线程是生产者,电梯是消费者,

除了主线程之外有两个线程,电梯线程和输入线程,输入线程负责在接收到请求后加入到调度器队列的队尾中,调度器通过队列实现,电梯线程负责从调度器的队头取出一个请求,然后走到请求的出发楼层,开门、上人、关门,然后走到请求的到达楼层,开门、下人、关门。

在调度器为空,且输入线程停止(遇到EOF)的时候,电梯线程停止,程序结束。

总体来说比较简单,在强测和互测环节中没有发现bug。

 

第二次作业是一个可捎带电梯,并且有负数楼层,不用考虑电梯的载客量。

我的调度方案是参考现实情况下的电梯,走到需要到达的最高层(考虑请求出发层和电梯内请求的到达层)后,折返,走到需要到达的最低层,然后再折返,运行期间在需要停靠的楼层(电梯内有人要到达该楼层,或者该楼层外面有人需要上电梯)停靠。

除了主线程之外有三个线程,电梯线程、输入线程、调度器线程(相比第一次作业而言新增),调度器线程负责在接收到请求之后把该请求放到相应的楼层数组中,并且计算出折返的楼层。

 

第三次作业比较复杂,三个电梯,有载客量的要求,每个电梯可以停靠的楼层不同。

我基本参考了第二次作业,调度算法也是和第二次作业差不多,但是对于不可直达、需要换乘的请求,我的思路是先把这些请求送到1层或15层,然后让这些请求到电梯外(相当于在1层/15层投放了请求),之后另一个电梯过来把请求带到相应的终点。

 

(2)度量

第一次作业:

 

第二次作业:

 

第三次作业:

 

可以看出,复杂度较高的是Elevator.run()和Tray.run(),是由于在这些方法中,我用了特别过程化的方式,这里确实有可以改进的地方。

 

(3)分析bug

前两次作业的强测和互测都没有发现bug,但是第三次作业强测和互测都被发现了TLE的bug,是因为程序最后停不下来导致的超时,在输入线程停止的时候对电梯线程处理不当造成的,这也是我考虑不够全面,以及本地测试不够全面造成的。

 

(4)发现bug的策略

由于多线程程序测试的难复现性,以及多线程程序与单线程程序的不同,我在本地测试的时候参考了这个帖子:

https://course.buaaoo.top/assignment/56/discussion/157

项目地址:https://github.com/Mistariano/buaaoo-elevator-test-suit

这个程序替换了原来的IO接口,可以定时投放请求,这样就可以进行黑箱测试了。

 

(5)心得体会

这几次的作业是有关多线程的,在思路上就与单线程的程序有很大的不同。我经历了第一单元的单线程作业之后,已经有了面向对象的思想,使得我在第二单元的作业中不会再出现特别面向过程的程序。这次作业的难点是要考虑线程安全,通过synchronized同步语句(但同时也要避免互锁),以及一些线程安全的类和方法,解决线程安全的问题。

猜你喜欢

转载自www.cnblogs.com/zzy-cnblog/p/10764737.html
今日推荐