电梯调度编写(oo-java编程)
第二单元的问题是写一个关于电梯调度的程序。
需要模拟一个多线程实时电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出。
主要锻炼学生的多线程程序编写能力。
由于需要实时的输入和输出,我们不得不采用多线程。
在这个单元中任务仍然被分为三个小任务:
①完成单电梯(随时允许输入)
②单电梯+(楼层增加负层,必须使用比先来先服务更加高效的算法)
③多电梯调度(增加重量限制、楼层停靠限制、换乘)
一、调度算法设计
单电梯的调度算法:
我在网上寻找调度算法后发现,网上大多的算法采用的都是静态算法,几乎没有动态算法。所以,我自己设计一个算法(或者说是参照实际使用中电梯的运转方式设计的算法),如下:
①查看该楼层是否有请求(包括进电梯和出电梯),有则开门转②,否则转③
② 让请求的人进出,并进行输出,所有请求进的人将这些人的出电梯请求同时加入电梯的请求序列中。关门转③
③沿电梯运动方向查看是否有任意类型的请求,如果有请求则向该方向运动一层转④,否则改变方向查看请求。如果在另一方向上有请求,则想这一方向移动一层转④。如果两个方向都没有请求则进程休息(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 | 5 | 2 |
| Main | 9 | 9 | 1 | 0 |
| Midlist | 26 | 26 | 5 | 2 |
| OrderClass | 46 | 42 | 2 | 7 |

diagram类图

Sequence Diagram



P2
oo度量
| LOC | NLOC | 方法个数 | 属性个数 | |
| Elevator | 219 | 206 | 10 | 7 |
| Main | 11 | 11 | 1 | 0 |
| Midlist | 33 | 33 | 6 | 2 |
| OrderClass | 46 | 62 | 2 | 5 |

diagram类图

Sequence Diagram



P3
oo度量
| LOC | NLOC | 方法个数 | 属性个数 | |
| Chart | 62 | 62 | 5 | 1 |
| Elevator | 307 | 278 | 13 | 14 |
| Entry | 8 | 8 | 1 | 0 |
| Main | 12 | 12 | 1 | 0 |
| Midlist | 367 | 322 | 21 | 19 |
| Orderlist | 46 | 42 | 2 | 5 |

类图

Sequence Diagram




前面的时序图看着太复杂,而三次作业的结构大致一致,于是我做了一个简易版的sequence diagram。

优点:在第一次作业的时候就做好了基础的调度设计,是一个比较有效的设计,在随后的两次作业中修改的内容相对较少,也没有第一单元的重构情况,从类图上看,大体的结构并没有很大的变动。由于调度器不是一个进程,并发控制的难度比较低。
缺点:功能不够独立,在新需求出现时,常常要重新独立出一部分功能。设计时缺少借口等这类设计,导致一修改需求就会违背oo的设计SOLID原则。实际上第一次的设计从某种角度上来讲是存在瑕疵的,调度器不是一个进程,所以调度器在功能欲发复杂的情况下越来越庞大,但是却没有并行性,某种程度上限制了运行的性能。
三、多线程的协同和同步控制
在第一次作业中,需要考虑如何停下自己的程序,我采用的是让中间的管道传递一个状态,即输入端是否关闭,如果关闭则再电梯的所有请求处理完后停止进程。
在第二次作业中,实际上并没有太多的改变(因为我第一次就已经做了优化),但是这次需要避免cpu轮循的问题。那么我在之前的基础上补充电梯wait的要求,应该是输入队列里没有东西,而且输入进程没有停止。
在第三次作业中,为了继承之前作业的架构,我并没有将调度器作为一个独立的进程。但是由于调度器中可能没有属于电梯的请求,这个时候电梯就应该wait,但是就算输入结束了也不能轻易的结束进程,因为有些人可能需要换乘(但这个需求可能还没有出现)。所以我做了下面一个表来处理这个相对复杂的问题。
| 电梯可以获得的请求 | 输入端 |
有无分割的请求 (换乘请求) |
电梯动作 |
| √ | - | - | 运行 |
| × | √ | - | sleep |
| × | - | √ | sleep |
| × | √ | √ | 结束 |
四、分析自己程序的bug
第一次作业中,程序结束的控制计较容易出bug,因为在程序结束输入的时候(ctrl+D),仅凭借队列里是否有未服务的对象是不够的,还需要有一个判断标志,在电梯每次轮循后对输入是否结束进行判断,从而决定是否结束电梯线程。
第二次作业中,由于不能轮循(因为太占cpu时间),所以必须使用wait/notify方法,这个时候需要考虑好线程有没有可能会死锁,如何才能保证不死锁以及如何控制线程结束。(这三个问题是第二次作业中比较重点的bug/问题)
第三次作业,由于程序难度的增加,程序的复杂,轮循和,进程意外退出,进程没有被唤醒再次成为问题的关键。在这一次中,我最后应该将轮循和进程退出可能的情况进行列表推演,当当靠脑子想这件事情是很不靠谱的!
五、寻找他人bug(我不做互测)
多线程中,PV操作及其重要,关于线程之间的变量必须synchronize,可以着重看这一部分的代码,而且各种状态的传播也会在这一部分中,这一部分代码是最容易出bug的。
根据这次多线程的特点,应该着重考虑多线程的死锁、轮循这两个问题,着重分析他人代码中占用的位置。而且多线程的bug不一定能够触发,所以可能要多试几次。
相比于第一单元,bug的查找更加困难,因为有一些bug是概率性出现的,所以在测试中可以能需要对一个测试样例输入多次(或者选择不同的时间节点输入)。
六、SOLID原则分析
S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写。
| SRP | The Single Responsibility Principle | 单一责任原则 |
| OCP | The Open Closed Principle | 开放封闭原则 |
| LSP | The Liskov Substitution Principle | 里氏替换原则 |
| DIP | The Dependency Inversion Principle | 依赖倒置原则 |
| ISP | The Interface Segregation Principle | 接口分离原则 |
SRP原则分析:在三次作业中,各个类的职责区分的非常清楚,启动线程、调度器线程、电梯线层、请求输入线程都能找到对应的类。
OCP原则分析:在这三次作业中(特别是第三次作业),我没有让三个电梯分别使用不同的策略(也就是说除了基础属性,其他他们都是相同的),所以不存在违背OCP原则的问题。
LSP原则、DIP原则分析:基于这次作业的难度,没有进行抽象和继承。
ISP原则分析:在设计的过程中,我并没有特别在意接口这个问题,所以我觉得这个单元的作业,在这个方面是有问题的。
七、心得体会
这次多线程的作业,让我全面理解了多线程。虽然在不需要涉及各种相对复杂的锁,但是仍然让我在大体上理解了多线程编写所需要的注意点。我希望接下来能够对我的编码进行指引,增加代码的限制,让我的代码更加工业化(能适应企业的要求)。
电梯调度编写(oo-java编程)的更多相关文章
- 电梯调度系统(界面由C图形库编绘)
1.编程题目 电梯调度系统 2.结对编程组员 黄冠译,刘畅 3.编程语言 C语言图形库 4题目要求 编写人员:刘畅,黄冠译 代码如下: # include <stdio.h> # incl ...
- OO第二次博客作业——电梯调度
OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...
- OO第二单元总结(多线程的电梯调度)
经过第一单元作业的训练,在做第二单元的作业的时候,要更加的有条理.但是第二次作业多线程的运行,带来了更多的运行的不确定性.呈现出来就是程序会出现由于线程安全问题带来的不可复现的bug.本单元的作业也让 ...
- OO电梯调度
告别了三次奇妙无比的求导作业之后,我们就开始搭建一部自己的电梯了.相信我们不同同学的电梯运行方式肯定各具特色吧,但值得肯定的是,在艰苦的走完了三次电梯逐步改进的作业之后,我们的电梯在正常情况下应该是可 ...
- oo第二次博客-三次电梯调度的总结与反思
本单元从电梯调度相关问题层层深入,带领我们学习并运用了了多线程相关的知识. 三次电梯调度依次为单电梯单容量.单电梯可携带.多电梯可携带. 一.我的设计 在第一次作业中,使用了最简单的FIFO调度方法. ...
- Java编程思想重点笔记(Java开发必看)
Java编程思想重点笔记(Java开发必看) Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...
- 【软件工程】电梯调度的初步实现 李亚文&&郭莉莉
一.开门见山,代码粘 using System; using System.Collections.Generic; using System.Data; using System.Drawing; ...
- java编程思想
Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理 ...
- Java编程思想(11~17)
[注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...
随机推荐
- PHP全栈学习笔记11
连接MySQL mysql_connect(servername,username,password); 面向对象: <?php $servername = "localhost&qu ...
- Android开发:UI相关(一)自定义样式资源
一.自定义样式资源: 1.在drawble中新建xml资源文件: 如果新建的xml文件没有自动放置在drawable文件夹下,就手动移动到drawable下. 2.编写样式代码: < ...
- Android开发:APK的反编译(获取代码和资源文件)
一.反编译工具: 1.APKTool: APKTool是由GOOGLE提供的APK编译工具,能够完成反编译及回编译apk的工作.同时,它也有着安装反编译系统apk所需要的framework-res框架 ...
- 每日分享!~ 使用js原生方式对拖拉元素(鼠标的事件)
一个元素放置页面上.如何进行拖拉,实现想放哪里就放哪里的效果呢? 效果如下: 如果让你写这个效果,你会如何写呢? --- 思路分析:我首先想到的是,对这个元素先绑定一个事件.(什么事件? 那当然是鼠标 ...
- redis学习--的持久化数据备份(RDB和AOF)
接上一篇:安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目 一.dump.rdb文件是怎么生成的 二.什么是redis持 ...
- 从PRISM开始学WPF(三)Prism-Region-更新至Prism7.1
[7.1update]在开始前,我们先看下版本7.1中在本实例中的改动. 首先,项目文件中没有了Bootstrapper.cs,在上一篇的末尾,我们说过了,在7.1中,不见推荐使用Bootstrapp ...
- 使用Aspose.Words将Word文档转换为Tiff格式图片文件
用Aspose组件的优点是操作Word文档不需要安装Office就可以实现. 首先需要引用Aspose.Words.dll,链接地址:链接:https://pan.baidu.com/s/1rJvjp ...
- 【spring实战第五版遇到的坑】3.2中配置关系映射时,表名和3.1中不一样
3.2章中按照书中的步骤写好相应类的映射关系,发现启动时,之前在3.1章中建的表全部被删重新建立了,并且Ingredient表的数据没了,由于使用了JPA,默认使用的是hibernate,在启动时会删 ...
- Sublime Text3介绍和插件安装——基于Python开发
Subime编辑器是一款轻量级的代码编辑器,是收费的,但是可以无限期使用.官网下载地址:https://www.sublimetext.com. Sublime Text3支持语言开发种类多样,几乎可 ...
- Skyline Te Pro二次开发技能总结
前两天项目开发中,忽然一个Imagelabel的参数不会调了,但是前段时间可是很熟悉的.好吧,好记性不如烂笔头! 1. 模型弹出窗调试 这里的模型弹出框指涉及到模型操作的,比如监听模型选定事件.根据窗 ...