一、概述
本单元通过多线程实现电梯调度,和上一单元相比较,更加侧重于线程的安全的模式。相较于上一单元难度有提高,整体来看,没有第一单元的学习结果好,三次作业中第一次第二次作业比较顺利,第三次作业因为线程安全的问题最后是无效作业,比较让人头痛。在调度策略上三次作业都选择了指导书中的ALS调度策略,没有更多的自己思考更高效的策略,也没有做到像研讨课上的大佬那样,对各种调度策略进行分析,并做出可视化的图表,最后优中选优,选择最好的调度策略,这是我没有努力做到的点,本单元的作业有很多的不足之处。
二、设计策略分析
这三次作业采用的是生产者——消费者的模式,输入作为生产者,电梯是消费者,他们之间由一个调度器相连。调度器中维护一个存储请求的队列。每次添加新的请求就把请求加入调度器队列。调度器再把请求分给各个电梯执行。电梯内部也有一个请求队列,按照ALS原则,每次以主请求为基准来控制电梯的运行,请求队列的请求逐渐变为电梯内部的请求,当请求输入、调度器请求队列、电梯内部请求队列同时停止时,程序结束。调度器的部分方法用synchronized修饰用于解决等待队列的同步和互斥问题。
第一次作业:单个电梯
第一次整体比较简单,设计的时候只需要一个生产者,一个请求队列作为调度器,还有一个电梯消费者就可以。按照上面讲过的方法:电梯的运行策略是,如果电梯内有请求,则优先处理电梯内请求;否则则接收电梯外最早到达的请求并执行,如果没有请求,则电梯停在最后完成请求的楼层不变。
第二次作业:多个电梯
第二次作业增加了电梯的数量和电梯中允许搭载的人数限制。我没有想到更多的优化算法,就选择使用取模的方法,将请求通过调度器平均分给每个电梯线程,调度策略方面没有什么改变,程序主要的迭代是在电梯线程中增加人数限制的判断,决定是否新人可以上电梯,调度器由简单的Arraylist变成了Arraylist中的每个元素仍然是Arraylist,把总的请求队列细分为不同电梯线程的不同专用请求队列。
第三次作业:多种电梯
我的第三次作业是无效作业,但是应该是线程安全方面有一些问题,设计策略设计方法方面我觉得应该还是可以说一说的。因为涉及到不同类型的电梯,乘客可能需要通过换乘才可以到达目的楼层,我就定义了1、5、15作为三个换乘楼层。请求处理方面和第二次类似,将请求分给A、B、C三种请求队列,再通过细化的请求队列分给不同类型的电梯线程。请求分配的原则:判断请求能不能不换乘一次完成,优先分配给不换乘的电梯,请求需要换乘的话,分配给Fromfloor存在于电梯停靠楼层的电梯。每次请求分配的优先级按照ABC的顺序(因为A类电梯的工作范围大于B类,大于C类。但是没有考虑ABC类电梯的载客容量的影响以及不同种类电梯数目对整体效率的影响,还是有很多优化提高空间),每种电梯依然采取ALS的策略,与第二次作业不同的是在电梯可以停靠楼层上要增加一些判断。
三、第三次作业架构设计的扩展性
整个电梯设计的思路一直都是生产者——消费者模式,对电梯种类的扩展可以通过在电梯类中增加属性和判断条件来实现,对电梯功能的扩展只需要和第一单元的作业类似,在电梯类中增加相应的方法实现就可以。对多种多数目电梯的综合调度,大部分也只需要改变调度器中的调度方法就可以完成扩展和改进。总体上讲,采用了适当的设计模式,那么明显感受到程序的扩展迭代性有了更多的加强。
四、基于度量的程序分析
第三次作业一直都是无效作业,所以在程序设计的时候更多一直在最后的找bug,没有对程序进行更多的优化和提高简洁性降低耦合度的过程,最后也没有找出bug
第三次作业协作图:
五、自己程序中的BUG
第一次作业:第一次作业的时候没有十分理解多线程的意义,在处理请求的顺序上没有按照输入的时候就开始处理请求,而是以输入所有请求都结束之后再开始电梯的处理,使得程序的性能极差,而且在强测中有一个点超时。
第二次作业:更多理解多线程之后,改变了第一次作业中处理请求的错误方式,也就没有出现bug。
第三次作业:最后应该是线程安全的问题,使得第三次作业无效,最后也是超时,还是对线程安全的理解不到位,而且发现了synchronized不能盲目修饰方法,因为修饰方法的时候就会锁住方法中的所有this变量,更应该明确操作中需要保护的this变量,了解每一步要干什么。而且对线程的工作方法要有很好的认知掌握,不能随便一个方法就notifyall(),就会把刚睡的线程无脑唤醒,造成超时和更多的麻烦。总之需要对线程之间的交互、线程安全有比较完全的认知理解才能写出对的程序……真的是学艺不精吃了大亏。
六、心得体会
1、程序的性能与正确性之间要做到很好的衡量,不能顾此失彼
2、选择一个很好的设计模式有利于后续的迭代开发
3、原来的oo作业都是想出方法之后没有急着去完成,每次都是留出的debug时间不是很多,结果第三次作业出现线程安全bug最后没有解决,作业翻车……以后oo作业要尽快努力去写
4、学习掌握自动化测试……提高debug的能力,并且在程序设计的时候尽可能严谨一些,少给自己挖坑(不会自动化测试真的深受其害
5、以后的oo学习要自己学的更用心努力……多看多学,要不然真的补给站了……无效作业真的可怕