电梯调度编写(oo-java编程)(等待指导书发布后内容补充)
第二单元的问题是写一个关于电梯调度的程序。
需要模拟一个多线程实时电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。主要锻炼学生的多线程程序编写能力。
由于需要实时的输入和输出,我们不得不采用多线程。
在这个单元中任务仍然被分为三个小任务:
①完成单电梯(随时允许输入)
②单电梯+(楼层增加负层,必须使用比先来先服务更加高效的算法)
③多电梯调度(guess,也有可能加上重量限制等)
一、调度算法设计
单电梯的调度算法:
我在网上寻找调度算法后发现,网上大多的算法采用的都是静态算法,几乎没有动态算法。所以,我自己设计一个算法(或者说是参照实际使用中电梯的运转方式设计的算法),如下:
①查看该楼层是否有请求(包括进电梯和出电梯),有则开门转②,否则转③
② 让请求的人进出,并进行输出,所有请求进的人将这些人的出电梯请求同时加入电梯的请求序列中。关门转③
③沿电梯运动方向查看是否有任意类型的请求,如果有请求则向该方向运动一层转④,否则改变方向查看请求。如果在另一方向上有请求,则想这一方向移动一层转④。如果两个方向都没有请求则进程休息(wait),等待唤醒,唤醒后转④。
④如果不在输入任何需求则结束,否则转①。
多电梯的调度算法:
多电梯我觉得可以在原来的基础上进行修改,在调度器分配请求时通过某种方式将请求分给不同的电梯,然后每台电梯按照单电梯的调度算法进行运行即可。由于本人的多电梯的调度算法效率比较低,所以这里就不多赘述,可以参考其他同学的多电梯调度算法。
二、程序分析
对每次的程序使用MetricsReloaded进行oo度量,使用diagram描绘类图
重要符号意义说明:
- ev(G)基本复杂度是用来衡量程序非结构化程度的.
- Iv(G)模块设计复杂度是用来衡量模块判定结构,即模块和其他模块的调用关系。
- v(G)是用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径的条数。
- LOC: Line of Code
- NCLOC:Non-Commented Line Of Code
P1
oo度量
LOC | NCLOC | |
Elevator | 183 |
169 |
Main | 9 | 9 |
Midlist | 26 | 26 |
OrderClass | 46 | 42 |
diagram类图
P2
oo度量
LOC | NLOC | |
Elevator | 219 | 206 |
Main | 11 | 11 |
Midlist | 33 | 33 |
OrderClass | 46 | 62 |
diagram类图
P3
oo度量
LOC | NLOC | |
Chart | 62 |
62 |
Elevator | 307 | 278 |
Entry | 8 | 8 |
Main | 12 | 12 |
Midlist | 367 | 322 |
Orderlist | 46 | 42 |
类图
优点:在第一次作业的时候就做好了基础的调度设计,后续的修改都不大。
缺点:功能不够独立,在新需求出现时,常常要重新独立出一部分功能。设计时缺少借口等这类设计,导致一修改需求就会违背oo的设计原则。
三、分析自己程序的bug
第一次作业中,程序结束的控制计较容易出bug,因为在程序结束输入的时候(ctrl+D),仅凭借队列里是否有未服务的对象是不够的,还需要有一个判断标志,在电梯每次轮循后对输入是否结束进行判断,从而决定是否结束电梯线程。
第二次作业中,由于不能轮循(因为太占cpu时间),所以必须使用wait/notify方法,这个时候需要考虑好线程有没有可能会死锁,如何才能保证不死锁以及如何控制线程结束。(这三个问题是第二次作业中比较重点的bug/问题)
第三次作业,由于程序难度的增加,程序的复杂,轮循和,进程意外退出,进程没有被唤醒再次成为问题的关键。在这一次中,我最后应该将轮循和进程退出可能的情况进行列表推演,当当靠脑子想这件事情是很不靠谱的!
四、寻找他人bug(我不做互测)
根据这次多线程的特点,应该着重考虑多线程的死锁、轮循这两个问题,着重分析他人代码中占用的位置。而且多线程的bug不一定能够触发,所以可能要多试几次。
五、Applying Creational Pattern
这次重点的模式应该是单例模式(第一次使用)以及观察者模式(应该在第三次作业使用)。单例模式被我使用参数传递的方法代替了,实际上使用单例模式会更符合设计结构。
