OO_Unit2——电梯模拟
Posted larryhawkingyoung
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OO_Unit2——电梯模拟相关的知识,希望对你有一定的参考价值。
OO_Unit2——电梯模拟
1 程序结构分析
1.1 Task1——单部多线程可捎带电梯
-
- 基本思路:
- 前言:其实不只是程序员,事实上每一个等电梯的人,在看着楼层显示屏中的数字离自己越来越近时,都至少有那么一刻会不自觉的与电梯设计者进行一次思想的交互,会站在设计者的角度来想象、模拟电梯的运行策略算法,有时还会不禁暗自称道其设计思路的高明。这次作业让我有幸能根据自己平时的体验来亲自设计一款具有自己风格的电梯,作为一只每天穿梭于宿舍与图书馆之间的贵系献祭者,自然对图书馆的电梯运行策略是再熟悉不过了,因此,本次设计的电梯就是基于自己经常搭乘的校图书馆电梯的设计思想,但是因为作业的性能度量基于电梯的角度,于是在捎带策略上牺牲了部分乘客的便捷性,从而实现整体运行时间最短。
- 两个线程,一个用于输入乘客请求(Input类),一个用于电梯运行控制(Controller类)
- 两个实时容器,一个存储电梯外正在等候的乘客(ReqQueue类 + Floor类),一个存储电梯类正在搭乘的乘客(Elevator类)
- Input类——ReqQueue类——Controller类 构成生产者消费者模式
- ReqQueue采用ArrayList<Floor>来分楼层建立队列,并且在每一个Floor中建立两个LinkedBlockingQueue<PersonRequest>,分别存储向上运行请求队列和向下运行请求队列,队列排序采用先来后到机制,ReqQueue由Input线程的输入实时更新请求队列并存储至具体的Floor
- Elevator采用TreeMap<Integer, LinkedBlockingQueue<PersonRequest>>存储其中的乘客,根据Integer(乘客的目的楼层),为每一个目的楼层建立一个乘客队列。同时Elevator类还记录的电梯当前的状态,包括当前楼层(currentFloor)、当前乘客数量(PassNum)。
- Controller同时根据ReqQueue和Elevator中的乘客队列,来控制Elevator的运行,包括goUp、goDown、openAndClose、exchangePassenger。采用的捎带策略是:
- 每到达一个楼层,就判断是否有乘客需要下,或者有同方向请求的乘客需要上,如果是,则exchangePassenger(包括相反方向的乘客,尽量避免下一次经过需要再开关一次)。
- 每到达一个楼层,就综合当前内外乘客队列,利用方法findNearestFloor来挑选出距离当前楼层最近的一个需要开关门的楼层,将其设定为当前的toFloor(当前电梯目的楼层),toFloor也是每到达一层就更新一次。
- 任务结束判断:在ReqQueue中维护一个isEnd标记变量,当Input输入为null时就setIsEnd为true并结束线程,当Controller检测到当前电梯内外乘客均为空时,就检查ReqQueue的isEnd,如果为true,就结束线程,从而结束整个任务。
- Metrics复杂度分析:经过合理的方法分解及类解耦,有效降低了复杂度,只有Controller.findNearestFloor(int currentFloor)存在硬伤,虽然它代码量仅仅只有20行,但是作为消费者,实现了队列为空时的线程等待,并且还有一个循环来获取当前最近的目的楼层。毕竟它是电梯运行及捎带策略的和核心部分,复杂度较高自然也很正常。
- 基本思路:
以上是关于OO_Unit2——电梯模拟的主要内容,如果未能解决你的问题,请参考以下文章