BUAA OO hw6架构简述
0.UML
1.关键类
-
管理纵向移动的等待队列和横向移动的等待队列的两个类:Building与Floor。两者本质都是生产者-消费者模型中的Tray,属于线程间的共享对象,需要对各方法进行synchronized保护。
具体实现方面,两者都采用了以ArrayList<Person>为元素的二维数组。即:
private ArrayList<Person>[][] req;
以Building为例,二维数组的第一个下标代表楼层,第二个下标代表方向,数组元素ArrayList即为某层前往某方向的等待队列;
e.g. req[6][0]代表目前处于六层、想要下楼的等待队列;req[9][1]代表目前处于九层、想要上楼的等待队列
在类中实现了putReq(), takeReq()等方法
-
纵向移动的电梯与横向移动的电梯:Elevator与ConveyorBelt。两者本质都是生产者-消费者模型中的Consumer,是两类线程。它们有三个状态:
- 状态0:电梯内有人,向下/顺时针运行
- 状态1:电梯内有人,向上/逆时针运行
- 状态2:电梯内无人
捎带策略与调度策略在后文有详细阐述
-
输入线程类:InputThread。本质是生产者-消费者模型中的Producer
2.调度策略
-
没有显式的设置主请求与捎带请求。由于两个本质为Tray的类中对等待队列的方向作出了划分,电梯只会让与运行方向相同的队列中的人登上电梯。
-
当电梯有人时,状态处于0 or 1,每改变一层决定是否开关门,从而实现捎带。
-
当电梯内无人时,需要重新确定电梯的运行方向。此时以该层以上的平均每层的人数与该层以下的平均每层的人数作为重新确定电梯运行方向的衡量指标,即:
dir = ((downNum * 1.0 / (curFloor - 1)) > (upNum * 1.0 / (FLOOR - curFloor))) ? 0 : 1;
环形电梯类似,比较顺时针半圈与逆时针半圈的人数
-
自由竞争
大道至简 -
加入电梯做好初始化后直接start()线程
3.架构亮点
- 较好地体现了面向对象的优越性。实际生活中,等待的队列分布在楼座的不同楼层,有上行下行两种方向;映射到解空间,引入以ArrayList<Person>为元素的二维数组,分楼层、方向管理;数据结构的相似性方便将现实问题的解决方法直接映射到解空间中;清晰明了
- 从本质上分析,本架构采用的调度策略与ALS相比,主要优化在电梯中无人后的电梯方向选择。本架构没有采用到达早晚时间的指标,而是采用该层以上以下的平均每层人数作为衡量指标,更加合理,利于提高电梯单位时间的吞吐量
- 将纵向移动与横向移动的队列、电梯彼此分离解耦,减少可能出现的线程安全问题
- 具有可拓展性。若需求更改为同时跨楼层、楼座移动,可以在电梯门开时检查下电梯的乘客是否已经到达目的地、若未到达直接加入另一类的等待队列
4.线程分析
本质只有两处线程安全问题:
- 给Building放置需求的InputThread线程与从Building取走需求的各个Elevator线程(共享对象为Building)
- 给Floor放置需求的InputThread线程与从Floor取走需求的各个ConveyorBelt线程(共享对象为Floor)
在本架构设计中,两处线程安全问题彼此独立、互不影响。
原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/245468.html