面向对象设计与构造 第二单元总结
面向对象设计与构造 第二单元总结
第一次作业
总体架构
MainClass负责线程的创建,InputRequest负责读入请求并将请求加入到请求队列中去,Elevator负责运行并根据其属性Scheduler的指令进行运行;为方便处理,将等待请求队列和电梯处理队列设置为Scheduler的属性,并将开关门和上下乘客的方法也写在Scheduler中,Scheduler每次处理后会向电梯返回一个int类型的值direction,电梯只需要通过当前位置position与direction相加实现上下楼。
同步块的设置和锁的选择
由于会被多个线程访问的仅有RequestQueue,因此我将RequestQueue的addRequest和deleteRequest方法用synchronized修饰,以此来防止增删的同时出现以实现线程安全。
调度器分析
对于我的Scheduler类,我将其作为Elevator的属性,在Elevator线程运行时根据Scheduler的返回值进行上下楼,开关门、进出乘客由Scheduler来进行。同时Scheduler与InputRequest共享请求队列,InputRequest负责加入请求,Scheduler负责删除请求,并将该请求加入到其属性eleRequest队列中去。
调度策略
大概采用的是LOOK算法,电梯启动后,每到达一层便查询本层是否存在与电梯运行方向一致的请求,如果存在则开门将其接入,若没有则查询电梯运行方向上是否存在未处理的请求,例如电梯上行,则查询电梯所在楼层以上的楼层是否存在请求,若运行方向上没有未处理的请求则根据请求队列是否为空来选择wait和向反方向运行。
第二次作业
总体架构
总体架构基本与第一次作业一致,在InputRequest中增加了创建电梯线程的功能,多部电梯Scheduler独立,共享同一个等待请求队列。
同步块和锁的选择
基本与第一次作业相同,区别在于为了防止多个电梯线程同时访问同一个请求,在RequestQueue中重写了get()方法,并使用synchronized修饰,并且标记已经被访问的请求,若访问已被标记的请求则会返回一个特定值。
调度器分析
每个电梯都有自己独立的Scheduler,所有的Scheduler共享同一个RequestQueue,Scheduler的设计与第一次作业一致。
调度策略
为了充分发挥电梯的主观能动性(偷懒),在多电梯调度的过程中采用电梯自由竞争的方式,即每个电梯都按照第一次作业的方式自主独立运行,首先到达请求楼层并成功取得请求的电梯将该请求加入自己的运行队列中并将该请求删除,其他未抢到请求的电梯继续根据Scheduler的指令运行。
第三次作业
总体架构
与前两次作业基本一致,但是将Scheduler作为抽象类,对于不同类型的电梯设计不同的Scheduler,但实际上需要改写的部分并不多,仅为方向的选择和可到达楼层的判断。
同步块与锁的选择
与前两次作业相同。
调度器分析
对于不同类型的电梯对相应类型的Scheduler稍作修改,主要体现在方向改变函数和乘客进出函数中。
调度策略
在第二次作业的基础上加入了简单的换乘策略,若B类型电梯在可到达楼层内取得了目标楼层不位于可到达楼层内的请求时,该电梯会将乘客送至距离目标楼层最近的奇数层;对于C类型电梯,考虑到其到达楼层,因此将其可接送的乘客请求稍微扩展为1-5楼,16-20楼,并将3楼和19楼作为换乘楼层以方便B类型电梯和A类型电梯接送。但由于部分判断写法有误,导致在强测和互测中没有完全实现我所设想的设计。
UML分析
UML类图

UML顺序图

可拓展性分析
功能设计
本次作业采用了电梯间独立运行、自由竞争的策略,因此在增加新类型电梯的情况下,不会对原有电梯的运行造成影响,并且由于并不牵扯到请求的分配,而是竞争后的方向改变,因此不会有过大的工程量,基本只需要复制粘贴类型A的Scheduler并稍作修改便可。若改变楼层数,例如增加负数楼层,则只需要在position与direction相加后进行判断是否为零,若为零则再执行一次加法即可。增加最高楼层则不需要特殊处理。
性能设计
由于采用LOOK算法和自由竞争,在增加新类型电梯后并不会对原有电梯的运行流程和性能产生过大的影响,新类型电梯也只是加入到电梯行业的内卷当中来。
BUG分析
第一次作业
强测与互测中均为出现BUG。
第二次作业
强测中未出现BUG。
互测中发现当请求数量少于电梯数量时会出现处于wait状态的电梯无法停止的现象。
第三次作业
强测中由于线程安全问题导致出现了CTLE,互测中也因为换乘策略和线程安全的问题被同房的数据HACK了两次。
HACK策略
由于太弱于是直接躺平任人宰割。
心得体会
线程安全
本单元的作业需要使用多线程的知识,这也是我初次接触多线程编程,从毫无头绪到逐渐理解,同时也见识了很多多线程相关的BUG也掌握了这些BUG的部分解决方法,在接下来的作业中会吸取之前经验教训,减少线程安全问题BUG的出现。
层次化设计
本单元作业对于整体架构方面未出现大规模的修改,仅仅在第七次作业对于不同类型的电梯增加了不同的Scheduler。并且所设计的类都是易于增量开发和修改的,因此这次作业我认为自己做到了层次化的设计。
浙公网安备 33010602011771号