BUAA-OO-电梯调度

1.设计策略

需求分析

设计一个系统,使其可以根据乘客的当前楼层和目的楼层,为乘客分配电梯资源并运送其至目的楼层。

自顶向下

根据需求,可以将整个系统分成三个部分:

  • 处理乘客的当前楼层和目的楼层,即输入处理
  • 为乘客分配电梯资源,即调度
  • 运送至目的楼层,即电梯本体

显然,这三个部分是有次序关系的:乘客输入,处理输入,将请求放入调度队列,调度器从调度队列中取出请求,根据各电梯状态将请求分配给合适的电梯。

上述的过程可以看成是三组 Producer-Consumer 组:

  • Producer: 乘客输入,Consumer: 输入处理
  • Producer: 输入处理,Consumer: 调度器
  • Producer: 调度器,Consumer: 电梯

输入处理

阻塞式获取输入,直到检测到 EOF 或者输入流关闭。处理后的请求存储在 PersonRequest 类中。当获取到合法请求,将请求存入调度队列,唤醒调度器。

调度器

从调度队列中取出请求,根据电梯状态来决定请求被分配至的电梯,对于需要换乘的请求,将后续请求也分配至同一电梯,待前置请求完成,重新对后续请求进行调度。这里的电梯状态包括但不止于电梯能够停靠的楼层、电梯当前运行状态、电梯当前的任务序列、电梯历史运行状态。前两者对于调度起着决定性的作用,而后两者主要是使得各电梯负载均衡。

电梯

从任务序列中取出任务,前往指定楼层执行任务。若完成了某个需换乘请求的前置请求,将后续请求提交给调度器,使其被重新调度。

2.具体实现

类的设置

elevator
├── Direction
├── Dispatcher
├── DivideTask
├── Elevator
├── ElevatorRequest
├── InputHandler
├── Main
├── RequestQueue
├── Task
└── Timer

InputHandler

顾名思义,用于处理乘客输入的类。域中包含有一个调度器(Dispatcher 类实例)。

当获取到合法输入时,唤醒(notify)调度器,否则堵塞。

当输入为 EOF 或者流被关闭时,将调度器的状态设置为停止状态(false),并唤醒(notify)调度器。

Dispatcher

调度器类。域中包含有

  • 一个调度队列(RequestQueue 类实例)。
  • 各个电梯(Elevator 类实例)。
  • 各个电梯的部分状态:能够停靠的楼层、电梯历史运行状态。

当调度队列为空,进入等待状态(wait)。

被唤醒后,从调度队列中依次取出所有请求并进行分配。全部取出后,若状态为运行状态(true),重新进入等待状态(wait);否则,将所有电梯的状态设置为停滞状态(false),并依次唤醒,最后结束调度器线程,但是保留调度器实例。

Elevator

电梯类。域中包含有

  • 电梯状态,包括开关门、运行速度,当前楼层,当前目标楼层。
  • 两个 Direction 类实例,一个用于表示当前的任务状态(向上或是向下),一个用于表示当前的运行方向。
  • 两个 ElevatorRequest 类实例,一个用于存储向上(目标楼层大于出发楼层)的任务,一个用于存储向下(目标楼层小于出发楼层)的任务。
  • 一个 LinkedList<DivideTask>类实例,用于存储将要被重新调度的后续请求。

电梯运行总体采用 Look 算法:在不转向的前提下先执行完毕一个方向的任务,然后切换为另一个方向的任务序列,继续执行。执行过程中的等待过程都通过 TImer 类来实现。

Task

任务类。单纯的数据聚合。域中包含有

  • 存储任务方向的字符串("IN","OUT")
  • 乘客 ID
  • 目标楼层

ElevatorRequest

电梯任务类。域中包含有

  • 两个 LinkedList<Task>类实例,一个是主任务序列,另一个是副任务序列。
  • 一个 Direction 类实例,用于表示任务序列的方向。

当电梯接收到请求,会将请求存入 ElevatorRequest 中。首先进行方向的判断,并将其拆分为两个任务:一个 IN,一个 OUT。然后判断加入主任务序列或是加入副任务序列:若与电梯的任务方向相反,或者可以捎带,则加入主任务序列,否则加入副任务序列。

当主任务序列为空,电梯转向时,进行 fresh 操作,将主任务序列与副任务序列互换。

DivideRequest

待调度请求类。单纯的数据聚合。域中包含有

  • 请求(PersonRequest 类实例)
  • 目标电梯

3.类图与复杂度分析

类图

如下,与上述的设计描述大致相同。

复杂度

使用 Complexity mertics 生成。

总体而言,复杂度尚可,复杂度较高的几个 method 都是与设计紧密相关的,没有修改或者拆分的必要。

4.自身 bug

在第二次电梯作业中,由于电梯的上下极限从 1-15 变为-3-20,而我在第一次作业中空任务的标志 Magic Number 设置为了 0 忘记修改,导致第二次作业出现了问题。由此可以看出测试的重要性,因而第三次作业我专门写了一个评测机放在服务器上进行长时间测试。

5.心得体会

在多线程编程中,要特别关注暴露在多个线程之外的副作用,严格控制进入临界区的线程数量。

BUAA-OO-电梯调度的更多相关文章

  1. OO电梯调度

    告别了三次奇妙无比的求导作业之后,我们就开始搭建一部自己的电梯了.相信我们不同同学的电梯运行方式肯定各具特色吧,但值得肯定的是,在艰苦的走完了三次电梯逐步改进的作业之后,我们的电梯在正常情况下应该是可 ...

  2. OO第二次博客作业——电梯调度

    OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...

  3. OO第二单元总结(多线程的电梯调度)

    经过第一单元作业的训练,在做第二单元的作业的时候,要更加的有条理.但是第二次作业多线程的运行,带来了更多的运行的不确定性.呈现出来就是程序会出现由于线程安全问题带来的不可复现的bug.本单元的作业也让 ...

  4. oo第二次博客-三次电梯调度的总结与反思

    本单元从电梯调度相关问题层层深入,带领我们学习并运用了了多线程相关的知识. 三次电梯调度依次为单电梯单容量.单电梯可携带.多电梯可携带. 一.我的设计 在第一次作业中,使用了最简单的FIFO调度方法. ...

  5. 「BUAA OO Unit 2 HW8」第二单元总结

    「BUAA OO Unit 2 HW8」第二单元总结 目录 「BUAA OO Unit 2 HW8」第二单元总结 Part 0 前言 Part 1 第五次作业 1.1 作业要求 1.2 架构设计 1. ...

  6. 「BUAA OO Unit 4 HW16」第四单元总结与课程回顾

    「BUAA OO Unit 4 HW16」第四单元总结与课程回顾 目录 「BUAA OO Unit 4 HW16」第四单元总结与课程回顾 Part 0 第四单元作业架构设计 架构设计概要 AppRun ...

  7. 电梯调度编写(oo-java编程)

    第二单元的问题是写一个关于电梯调度的程序. 需要模拟一个多线程实时电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出. 主要锻炼学生的多线程程序 ...

  8. BUAA OO 2019 第二单元作业总结

    目录 总 架构 controller model view 优化算法 Look 算法 多种算法取优 预测未来 多线程 第五次作业 第六次作业 第七次作业 代码静态分析 UML 类图 类复杂度 类总代码 ...

  9. 学会拒绝,是一种智慧——OO电梯章节优化框架的思考

    在本章的三次作业里,每次作业我都有一个主题,分别是:托盘型共享数据.单步电梯运行优化.多部电梯运行优化,因而电梯优化实际是第二.三次作业.虽然后两次作业从性能分上看做得还不错,但阅读其他大佬博客,我深 ...

  10. 【软件工程】电梯调度的初步实现 李亚文&&郭莉莉

    一.开门见山,代码粘 using System; using System.Collections.Generic; using System.Data; using System.Drawing; ...

随机推荐

  1. UOJ #269. 【清华集训2016】如何优雅地求和

    UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...

  2. Shell 全局变量、环境变量和局部变量

    Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他 ...

  3. 机器学习:利用K-均值聚类算法对未标注数据分组——笔记

    聚类: 聚类是一种无监督的学习,它将相似的对象归到同一个簇中.有点像全自动分类.聚类方法几乎可以应用于所有对象,簇内的对象越相似,聚类的效果越好.聚类分析试图将相似对象归入同一簇,将不相似对象归到不同 ...

  4. mysql查询order by 指定字段排序

    当MySQL查询时排序的字段不是数字时而是汉字的时候也可以用when  then 来指定排序. 列如yewu_check表的status 字段不是0,1,2而是汉字待办,已办,退回.可以如下写法: S ...

  5. 【刷题】Git知识点

    参考:学习总结之Git学习-总 1-origin是什么? 答:origin 是默认的远程版本库名称,可以在 .git/config 之中进行修改.在默认情况下,origin指向的就是你本地的代码库托管 ...

  6. MySQL--7种join连接

    一,定义: 1)LEFT JOIN / LEFT OUTER JOIN:左外连接 左向外连接的结果集包括:LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行.如果左表的某行在右表 ...

  7. 小程序ios开发注意点

    两个月了啊,这两个月完成了一个vue的项目还有一个小程序,终于可以休息一下了, 今天先声明一个奇怪的bug,在我开发微信小程序的时候, 发现有个获取商品详情的接口在安卓手机上是可以获取数据的, 但是i ...

  8. 使用sqlserver 链接远程服务器进行查询

    --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogi ...

  9. LinkedHashMap基本原理和用法&使用实现简单缓存(转)

    一. 基本用法LinkedHashMap是HashMap的子类,但是内部还有一个双向链表维护键值对的顺序,每个键值对既位于哈希表中,也位于双向链表中.LinkedHashMap支持两种顺序插入顺序 . ...

  10. http请求方式和传递数据类型

    HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则. GET,通过请求URI得到资源 POST,用于添加新的内容 PUT用于修改某个内容 DELETE ...