OO第二单元电梯调度总结

摸鱼特等奖选手 学生 2024-04-19 22:27:31

第一次作业

1.设计思路:

首先是“多线程”。将整个过程分为三个线程,分别为输入线程(InputHandle)、调度线程(Schedule)、电梯线程(Elevator)。输入线程负责将输入的请求加入到waitQueue中,而调度现场负责将waitQueue中的请求分装到每个processingQueue中,每个电梯处理其相对应的processingQue即可。

其次是电梯的调度算法,我采用了LOOK算法,即判断电梯在每一层的状态,再给出相应的策略,具体算法如下:

1.判断是否有人进出(如果有人进出,则开门)

注意:如果该层的请求与电梯现在运动的方向相反,不开门。例如,电梯现在在6层,方向向上,有人想从6层到2层,此时不开门。

2.进出过程结束后,判断电梯内是否还有人:

电梯内有人:继续沿当前方向移动(如果电梯已经到了11层或者1层,需要改变方向)

电梯内无人:判断队列中是否还有请求,没有新的请求的情况下,队列结束则整个程序结束,队列未结束就继续等待请求。

在队列中还有请求的情况下,判断请求的方向在电梯运动方向的前方还是后方(直接从下一层开始判断),如果在“前方”有请求,就继续沿当前方向运动,否则,就反向。(比如,此时在10层,只有一个从10层到2层的请求,就将电梯运动方向改为反方向)

2.类的设计与构造

根据算法设计相应的类。Person类负责管理每个请求的信息,包括个人id,所在层与目的地层,所在楼号。

采用一个RequestTable来管理请求队列,类中有一个Arraylist<Person>和一个布尔型变量isEnd。设计一个OutputHandle类来输出电梯的每一个动作。电梯类中包含有电梯的信息,以及相应的RequestTable类变量processingQueue。

在电梯类中,为了保证方法的可拓展性,设计相应的move()、open()等方法,放在run()中运行。

由于线程之间的互斥问题,RequestTable中的方法需要加锁。

3.类和方法的复杂度

4.类图

 

 第二次作业

1.调度策略:

本次作业直接采用随机数的方式分配电梯。

2.新增Reset指令:

将Reset指令当做普通指令处理,在Schedule类中,Receive之前先判断电梯是否正在Reset,在Reset的话就换一个电梯序号。

由于Reset指令要马上处理,因此,在Elevator类中每次电梯动作之前都先判断此时队列中有无Reset指令,如果有,先执行Reset,并把电梯队列的状态设置为正在重置。

Reset指令后,我采取的方式是将人重新归还到电梯队列,等待Reset完成后再重新receive到电梯中。

类图同第一次。

 

第三次作业

1.新增双轿厢重置:

新建双轿厢电梯类,继承原先电梯类的队列和id号。设置A梯的顶层(Topfloor)为换乘楼层,B梯的底层(BottomFloor)为换乘楼层。

在Schedule中新增DoublecarReset,优先进行重置。当Elevator类中接受到指令时,直接关闭当前线程,新开启两个双轿厢线程。

2.处理换乘楼层

两部电梯不能同时访问换乘楼层。可以重设一个changeFloor类,在其中给访问方法加锁。电梯在移动之前调用此方法,判断是否到达换乘楼层。

3.如何重新Receive

采用两个等待队列的方式,将原电梯的一个队列直接分成两个,分别进入两个队列中。在换乘过程中,直接进入到另一个队列(可以通过判断ToFloor判断要去往哪个队列)

心得体会:

多线程的设计确实比较有难度,在设计的时候多次遇到了线程无法被唤醒或者CPU轮询的情况,且多线程debug确实是一个难题。不过好在通过本机测评次数多和print法修复了很多bug。关于电梯性能方面,其实自己的方法考虑性能比较少,主要考虑的还是正确性。采用随机数的方式性能其实不太稳定,不过感觉这种调度方式设计比较方便,且不太会出什么错误,还是选择采用。

主要的一个劣势就是没有把人送回原请求池,而是直接塞到了电梯的队列中,主要的考量是怕电梯的结束出现死锁现象。

...全文
38 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧