OO第二单元总结

OO第二单元总结

任务概述

本单元作业的任务目标是模拟多线程实时电梯系统,主要考察线程安全问题、多线程交互,以及多线程架构的协同设计方法和电梯调度方法。

第一次作业(hw5)

UML类图

架构设计以及调度器设计

第一次作业采用了生产者消费者模式。MainClass主类初始化五部电梯、输入线程InputManager以及调度器Schedule。输入线程将请求放入等待队列中,由调度器负责将请求从等待队列中取出,放入对应的请求队列中,每个楼座有对应的一个请求队列。最后电梯从对应楼座请求队列中取出请求并将乘客送入对应楼层。调度策略选择ALS策略。

线程安全设计

这次作业的线程安全设计比较简单粗暴,把请求队列类中的所有方法加锁。电梯类中对检索队列改变运行方向(changeDirection())、搜索该层是否有乘客需要进入(hasIn())以及乘客进入电梯(getIn()))三个函数中对请求队列加锁。由于第一次作业比较简单,所以并没有出现轮询等错误。

发现的BUG

在电梯调度时出现BUG,导致电梯会在1层和0层之间来回移动。通过加入对于电梯开始时1层有乘客的状况的特判解决了BUG。

在输入队列结束时如果电梯中还有人会强制结束程序,发现是判断电梯结束时忘记加上对于电梯内人数是否为0的判断,导致提前结束。

Hack策略

只在一部电梯里加入很多相距较远的请求,测试电梯的调度策略是否高效,来找出RTLE。同时在五部电梯中加入请求测试电梯的线程安全问题。一共hack到了5次。

第二次作业(hw6)

UML类图

架构设计以及调度器设计

与之前的架构基本相同,加入了横向电梯类FloorElevator。除了在方向选择上加入了循环以外与横向电梯没有太大的改动,调度策略也基本类似。对于调度器加入了判断请求类型,如果是乘客请求则与第一次作业相同,将其加入对应的楼座或者楼层队列;如果是电梯请求,则通过方法addElevator()来加入电梯。所有的楼座和楼层队列(共5+10个)均在主类中完成初始化,所有电梯自由竞争所在楼座、楼层的请求队列。

线程安全设计

与上一次作业相同。

发现的BUG

把判断队列是否为空、是否结束以及队列大小的方法加入了多余的notifyall,导致出现轮询。在输出线程安全上忘记加入类来保护,导致没有进入互测。加入输出保护类Myoutput类后修复了大多数bug。剩下的BUG为RTLE,为调度策略方面的问题,没有修复。

Hack策略

没有进入互测,故没有hack。

第三次作业(hw7)

UML类图

UML时序图

架构设计

依然使用生产者消费者模式。将加入电梯的方法移到输入线程InputManager中,调度器处理全部的乘客请求,电梯请求之间在输入线程中完成。用Person类包装乘客请求。由于加入换乘,在Person类中要设定请求的换乘楼座、楼层和终点楼座、楼层,并用boolean类型的transfer来表示是否已经换乘过,每次换乘过都要改变tempToFloor和fromFloor。在调度器将请求放入楼座、楼层请求队列时,将对应电梯的transNum+1,当乘客被送出时-1,最终电梯终止需要transNum=0来防止换乘时的电梯已经停止运行。调度策略上与之前的相同。由于没有处理好电梯自由竞争时如何改变对应的transNum,所以本次实现仅用了初始六部电梯。优点是稳定性较好,虽然容易RTLE但是不容易出其他BUG。

线程安全设计

与上一次作业相同,锁住请求队列类中的方法,电梯中需要访问请求队列的方法中锁住队列。对于电梯中transNum的改变方法addTransNum()中也加了锁。

发现的BUG

在加入换乘时出现了在输入的请求队列结束时遇到换乘目标电梯却停止运行的情况,通过在接受请求时预先将需要用到的所有电梯的transNum+1来防止电梯提前停止运行。由于只用了6部电梯,所以出现了RTLE,且由于架构问题并没有修复。

Hack策略

与第一次作业时的相同,但是没有hack到人。

未来可能的扩展方向

1.输出乘客的整个运动路线,将乘客的中转、终点电梯和楼层、楼座都存入Person类中。

2.同时处理不换乘和换乘的请求(稍微改动一点就行)。

3.加入仅在制定楼层停靠的纵向电梯(与本次作业中横向电梯的要求类似)。

总结与心得体会

第二单元的三次作业对我的自信心得到了加强,不再像第一单元那样迷茫。虽然有一些BUG没有修复,但是比第一单元时通不过中测要好了很多。对三次作业的迭代开发让我对于多线程的设计、死锁轮询的解决、调度策略的设计都有了更深的理解。三次作业的架构基本相同,这让我省去了不少的时间,并把这些时间花在理解多线程编程中。

多线程的架构对于线程安全要求很高,加锁、加notifyall等一些小细节都会导致轮询或者死锁的产生。第三次作业时就产生了轮询,通过“打印法”的不断试错终于让我找出了问题的源头,并成功解决,让我真实地感觉到我的OO能力的提升。虽然成绩还是一般,但是让我有了学习的动力以及信心,提高了架构设计以及DEBUG能力,感觉到收获颇丰。期待下一个单元的挑战。

posted @ 2022-05-03 23:08  JcDt  阅读(31)  评论(0编辑  收藏  举报