OO电梯做业总结算法
这三周的做业和课堂内容以及OS的课上内容都相同,都是关于多线程方面的知识。在此次做业中由浅入深布置了三项多线程电梯方面的做业,让咱们在实践中感觉了多线程的工做原理以及各项须要注意的要素。编程
1、第一次做业多线程
第一次做业是典型的生产者消费者问题,只不过生产者没必要考虑容器装满的特殊状况。在此次电梯做业中电梯只须要将乘客送往目标楼层,不须要解决沿路搭顺风车等其余须要解决的特殊状况。当负责输入的生产者中止时,设置一个共享的结束变量结束整个电梯的运行,整个电梯的运行结构以下图所示:架构
如图所示,整个电梯总共包含2个线程,即电梯线程和输入线程,二者经过结束信号进行通讯。同时二者共享一个共享变量:等待队列。在多线程环境下势必会出现二者共同访问致使数据冒险的状况。我采起的解决方法是将等待队列类中的每一个函数设定为静态函数,并加上synchronized修饰。经过百度和自身的实践,这样操做的实际效果是对类自己进行加锁,即当一个静态函数被调用时禁止其余静态函数被调用。这样操做的确可行,可是因为是在函数上加锁,性能方面不如对特定变量,但好处是可以有效地确保正确性。函数
本次做业的类图以下所示:性能
代码分析以下:学习
能够看见在电梯类中个人写法没有作到彻底对任务进行细分,而是一个run方法走到底,所以代码的复杂性较高。在接下来的任务中我注意到了本身的问题,对任务进行更细的划分。测试
BUG分析优化
这一次做业因为比较简单,在互测以及强测中都没有发现任何BUG。spa
第一次电梯做业总结
第一次做业是对多线程的试水,在其中我初步感觉到了多线程的设计风格,同时大体确立了电梯问题的整个架构。在接下来的做业中都是沿用输入队列,等待队列以及电梯3类的架构进行设计。
2、第二次做业
这一次的电梯做业相比上一次的电梯做业增长了2个难点。第一,这一次的电梯是ALS电梯,须要额外考虑2个环节。首先电梯在上升时须要考虑对同方向乘客的捎带,同时因为电梯内部可能有多于一个乘客的状况,所以须要额外增长一个队列记录电梯内部的人员请求。第二,这一次做业增长了对于CPU运行状况的检查,所以没法在这一次做业中使用轮询算法,必须运用锁控制查询,下降CPU使用率。
受到OS课程的影响,相比较synchronized,notify(),我偏向更加简单直接的Semaphore,所以在此次做业中我主要使用Semaphore实现进程同步和互斥。
首先列出此次做业的主要流程架构:
捎带的解决方法如图中所示。首先创造运行队列,将电梯中的全部人的请求加入运行队列。其次在每一层都检查等待队列中是否有知足捎带条件,若是有则加入运行队列中。最后再谈谈我是怎么解决轮询问题的,我所采用的方法是最简单的方法,即在每次搜索结束以后进行sleep操做,减小CPU使用。固然合理利用信号量确定是最高效的解决方案,所以在第三次做业中我采起了另外一种方案。
如下是本次做业的类图以及代码分析:
因为此次电梯做业中啊须要使用到大量的if判断,包括电梯的运行方向,查找操做以及判断当前层数是否为0等,所以此次的代码复杂度广泛较高。能够改进的作法是对函数功能进行进一步的细分。在这一次做业中为了更高的准确性和代码的直观性,我没有进一步细分,致使代码复杂度较高。
BUG分析
在中测中主要出现了一个BUG,就是CPU超时,经过sleep()即可顺利解决。然而强测只得了26分,缘由特别简单,也特别愚蠢。在电梯向下运行进行顺带判断时,不慎将>写成了<,直接致使测试点全挂。也算是一个教训。代码上任何一点微小的错误将致使整个崩盘,所以必须在每次中测时作好课下测试,写本身的评测机,最大限度地杜绝这种状况再次出现。
3、第三次做业
第三次做业本质上相较于第二次做业增长了2个方面。第一是电梯变多了,所以须要创造更多的运行队列,同时对等待队列须要进行访问加锁控制。第二点也是此次做业的难点,因为部分请求没法由一个电梯完成,所以须要采起合理可行的措施实现多电梯协做。对于该问题的解决我经过改写PersonRequest类实现,在其中添加了label,realend,available三个变量进行实现,对这种特殊状况的处理在等待队列中实现,具体方法以下图所示:
对于个人处理架构,在此次做业其实还有一个隐藏的难点,那就是一台电梯关闭时机的判断。当输入线程关闭时且等待队列为空时不可以关闭电梯,由于label=1的运行队列中的请求会从新加入等待队列。解决方法有2个,第一是让每一个电梯线程可以访问其余电梯的运行队列,当输入线程关闭,全部的运行队列都为空而且等待队列为空时,同时结束全部电梯线程。我认为电梯运行队列应该由本电梯彻底掌握,所以采起第二种作法,在输入线程结束而且等待队列为空的状况下,当等待每部电梯都处于查询等待队列状态而且第一次查询未找到时,将每部电梯的一个特征变量设置为1,当全部特征变量设置为1时,同时关闭全部电梯。
整体上这一次做业的队列类以及电梯很好地复用了上一次的做业,对电梯的修改是增长了对label=1任务的特殊处理,对满员状况的判断以及在线程结束时的特殊处理。对队列的修改包括增长了2个运行队列,以及在将输入线程的请求读入等待队列时判断可执行的电梯,写入available,同时对不可执行的电梯做label=1的特殊处理,第三次做业的类图以及代码分析以下图所示:
这一次的代码风格明显有很大的不足之处,缘由之一是这一次的做业大幅度复用了上一次做业的样板,所以在电梯类中代码的复杂度较高。第二个不足之处是没有在电梯类中实现继承或者建立一个泛化的电梯类。此次做业中三个电梯明显有很大的相同点,只是在个别属性上不一样。将代码进一步细化而且熟练实现以及掌握继承是须要在接下来的学习中注意的地方。
BUG分析
这一次的做业比上一次更加悲剧,中测未能经过。最终发现缘由也特别简单,在电梯顺带时彻底沿用了上一次的模板,忘记进行修改,致使电梯在等待队列提取请求时根本就没有判断当前楼层是否能停靠,直接致使整个测试崩盘。这也给我带来了第二个教训,那就是不能太急着写代码,而是应该先详尽地对整个任务进行细节分析,列出全部须要扩展的地方再进行修改,不然就会像这样在细节处崩盘。
4、互测BUG分析策略
首先这一次的电梯做业测试难度明显上升,没法运用简单的控制台输入输出获得正确结果,所以在正式进行测试以前我经过讨论区的指示本身写了一个评测机,在另外一个文件中间段输出本身设定的指令,同时替换输入线程的方法,经过process类读取文件中的指令实现按照特定时间输入的效果。
第一次做业互测:这一次做业的互测其实并无太多BUG能够发现。我注重两方面的BUG,一是对电梯关闭时机的测试,第二则是电梯是否可以正确运行。结果并无在互测中发现BUG。
第二次做业互测:这一次做业我受到了屡次攻击,主要来自于强测的错误,将>误写成<.这一次的强测我注重两个方面的测试,首先是在边缘时间投放测试点,即电梯关门的瞬间投放请求,若是在开门时搜索等待队列则会错过该请求。第二是对电梯运行经过0层的测试,在互测中共DE出2个BUG。
第三次做业互测:因为没有经过中测,所以很不幸没有进入第三次互测。
5、心得与体会
多线程处理无疑是每一个程序猿的基础技能,此次的做业只是为咱们开了一个很是初步的头,接下来还有无穷无尽的知识点须要咱们本身去探索。在此次做业中虽然成绩不够理想,可是静下心来仍是得到了很多的经验和教训,包括对编程方法的反思,对细节的把握,以及代码风格架构的进一步优化,这都是我须要在接下来的做业中不断改进的地方。在接下来我须要更进一步,积极了解阅读关于JAVA方面的常识和知识,使得本身具备更增强大的专业技能,同时让本身不至于在细节处再次翻车。