OO第二单元——多线程(电梯)

OO第二单元——多线程(电梯)

综述

第二单元的三次联系做业都写电梯,要求逐步提升,对于多线程的掌握也进一步加深。本次做业所有都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题。正则表达式

第一次做业——单部电梯(无调度)论述

第一次做业,是写一部电梯的模拟器,指导书提供了一个极为基础或者说不叫算法的算法,只须要将人送到正确楼层便可,对于时间、性能没有任何要求,但也是咱们第一次尝试多线程,开始写代码时对于wait(),notify()函数并非十分了解,致使出现了各类线程不安全,或是出现死锁的情况,代码写得也比较的复杂,架构并非十分清晰。算法

性能分析

方法复杂度

明显能够看出run方法复杂度较高,其余方法为正常水平。数组

类复杂度

因为没有任何性能要求,我采起了接完一我的再去接另外一我的的方法,效率极低,但能够保证正确性,创建了两个线程,一个Producer线程,负责读取输入,并放入共享队列中,另个一个Consumer线程,负责处理共享队列中的指令,并指导电梯上下移动,而在此次做业中我将电梯和Consumer写在了一块儿,也就是没有调度器线程,而只有生产者、消费者。安全

在后期,我也遇到了一些问题,好比结束程序的问题,我在Ctrl D后,并不能结束进程,而是卡在了一些死循环或是wait里,最终我也在用了信号量的状况下多加判断,结束进程。多线程

 

第二次做业——单部电梯(ALS调度)论述

第二次做业,与第一次做业要求并没有太大差异,只是增长了地下楼层,也就是负数楼层, 但在性能上有所要求,指导书给出了ALS算法,即捎带算法,在电梯运行过程当中捎带路过楼层的乘客,相较于第一次做业的FAFS算法,有了很明显的进步,性能大大提升,难度也有所提升。输入输出接口仍然给好了jar文件,无需咱们担忧。下面先看一下IDEA对于我代码的分析。架构

类图

方法复杂度函数

 

复杂度较高的几个方法中都包含了较多的if条件判断,为确保正确性,只能以性能换正确。代码设计并非十分到位。性能

类复杂度

 

第二次做业,我按照指导书使用了ALS算法,每到一个楼层,我会先让进程sleep(400),以度过开关门时间,而后检测电梯的等待队列中,是否有当前楼层的乘客在等待,如有则进入电梯乘客队列,接着遍历电梯乘客队列,将到达楼层为当前楼层的乘客送出电梯,每一次电梯运动前,都会更新一下当前的目标楼层,目标楼层也会综合考虑等待队列中的出发楼层,而后电梯根据目标楼层选择向上运动或向下运动,每运动一层为一个周期。测试

我认为此次做业的难点也就主要在调度一块,如果调度算法太差会致使Real-Time-Limited-Exceed,如果暴力轮询不sleep()会出现CPU-Time-Limited-Exceed,这也是我后面本身试出的一个小技巧,因为对于wait(),notify()两个方法的理解不到位,个人电梯内部采用暴力轮询,以防止错过任何一条指令或是进程在等待i队列还有指令的时候就结束。 可是我在获取指令的进程中采用了notify(),以唤醒get()方法中的wait()。spa

第二次做业我并非十分红功,因为我的架构太失败,致使调度环节出问题,电梯运行方向并不会正确的改变,致使在强测时挂了多组数据,未能进入互测,此次做业我吸收了教训,知道一个不正确的架构,必定写不出一个正确的程序,在开始码代码前必定要考虑周全,想到程序运行的每一方面,尤为是结束进程方面,必定要在开始之初就设置好信号量,作好规划,而不能等到写完程序后在程序内部打补丁,强行结束程序。

 

第三次做业——三部电梯(自行调度)论述

第三次做业提升要求,设置为三部电梯,且每台电梯可以到达楼层互不相同,也就致使了须要乘坐两台电梯才能到达目标楼层的操做,且每台电梯运行速度,最大承载量也不相同,一开始我想使用继承,一个父类电梯包括电梯全部操做,而后用子类修改电梯的各类数据,造出三台电梯,但后来我发现了更加直接的方法,使用构造方法来肯定电梯的几个参数,无需使用继承,且继承run方法我也不太肯定是如何运行的。下面先看下IDEA的分析。

性能分析

类图

方法复杂度

复杂度高的函数如Tray.get(),由于三台电梯不一样,致使获取的目标也不一样,也就是用了if判断语句,增长了复杂度,但之后可使用数组,传入index以减小if的使用,而在获取aimFloor一块,依然复杂度极高,毕竟有多种状况,我只能使用if判断,手动判断状况。

类复杂度

 

第三次做业我仍是使用了生产者-消费者模式,因为会出现一台电梯没法送达的状况,我选择在当初将指令放入等待队列时,便拆分好,我会考虑全部的中转楼层,选取其中路线最短的中转楼层,而后将前一条指令先放入恰当的电梯中,后一条指令放在个人Monitor线程中,这是我新开的一个监视者线程,负责查看出电梯人员中,是否有id与监视者的等待队列中的id相同,如有,则该等待队列中的指令放入适当的电梯等待队列中,其余的架构都与第二次做业都差很少。

第三次做业的强侧表现也不太好,在这里我分享一下我debug的经历,我频繁出现CPU-Time-Limited-Exceed的问题,根据以往的经验判断,必定是暴力轮询没有sleep致使的,但我也并非很清楚是哪个while循环出现的暴力轮询,因而我才用输出debug的方法,在每个while循环内部都都增长了输出,“XXX(类名):XXX(方法名) Here!”, 以判断哪个while出现暴力轮询,固然输出结果极其恐怖,一个txt文件里面有25w+行的输出,显然找到了bug所在,可是本身在课下测试时并无仔细测试。

这一次的经历也教会了我使用JProfiler,能够在Thread模块,查看是否有block,如果出现block,即代码内容有问题,而后使用输出debug,找到bug所在。

同时,在研讨课上,也有同窗分享了System.error方法,能够输出错误数据,之后debug时能够尝试。

相关文章
相关标签/搜索