第二单元的问题是写一个关于电梯调度的程序。

需要模拟一个多线程实时电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出。

主要锻炼学生的多线程程序编写能力。

由于需要实时的输入和输出,我们不得不采用多线程。

在这个单元中任务仍然被分为三个小任务:

①完成单电梯(随时允许输入)

②单电梯+(楼层增加负层,必须使用比先来先服务更加高效的算法)

③多电梯调度(增加重量限制、楼层停靠限制、换乘)


一、调度算法设计

单电梯的调度算法:

我在网上寻找调度算法后发现,网上大多的算法采用的都是静态算法,几乎没有动态算法。所以,我自己设计一个算法(或者说是参照实际使用中电梯的运转方式设计的算法),如下:

①查看该楼层是否有请求(包括进电梯和出电梯),有则开门转②,否则转③

② 让请求的人进出,并进行输出,所有请求进的人将这些人的出电梯请求同时加入电梯的请求序列中。关门转③

③沿电梯运动方向查看是否有任意类型的请求,如果有请求则向该方向运动一层转④,否则改变方向查看请求。如果在另一方向上有请求,则想这一方向移动一层转④。如果两个方向都没有请求则进程休息(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编程)的更多相关文章

  1. 电梯调度系统(界面由C图形库编绘)

    1.编程题目 电梯调度系统 2.结对编程组员 黄冠译,刘畅 3.编程语言 C语言图形库 4题目要求 编写人员:刘畅,黄冠译 代码如下: # include <stdio.h> # incl ...

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

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

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

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

  4. OO电梯调度

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

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

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

  6. Java编程思想重点笔记(Java开发必看)

    Java编程思想重点笔记(Java开发必看)   Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...

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

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

  8. java编程思想

    Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理 ...

  9. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

随机推荐

  1. ajax data属性传值的方式总结

    在和后台同事对接口的时候,有一个小问题一直困扰着我.那就是用ajax请求后台接口数据,需要用data属性传值的时候,data属性传值的方式感觉没有统一用一种方式. 后来仔细想想,其实哪种方式都可以,主 ...

  2. mysql数据库打开连接时报错:1251

    考试之前由于一直在做团队项目导致疏忽了数据库 等到今天来连接做考试的时候发现报错:1251 网上的解释以及解决方法: 今天下了个 MySQL8.0,发现Navicat连接不上,总是报错1251: 原因 ...

  3. Vue.js-04:第四章 - 页面元素样式的设定

    一.前言 前端开发中有三大件:HTML.CSS.JavaScript,在前面的学习中,不管是学习 Vue 的指令系统还是 Vue 的事件修饰符,主要还是针对的是我们在前端开发中的 JavaScript ...

  4. debian The type initializer for 'System.Drawing.KnownColors' threw an exception

     Change the "System.Drawing" reference of "CoreCompat.System.Drawing"if you thro ...

  5. 高性能消息队列NSQ

    前言 最近我再网上寻找使用golang实现的mq,因为我知道golang一般实现的应用部署起来很方便,所以我就找到了一个叫做nsq的mq,其实它并不能完全称为队列,但是它的轻量和性能的高效,让我真的大 ...

  6. 一套代码小程序&Web&Native运行的探索02

    接上文:一套代码小程序&Web&Native运行的探索01,本文都是一些探索性为目的的研究学习,在最终版输出前,内中的内容可能会有点乱 参考: https://github.com/f ...

  7. element-ui 动态换肤

    1.在安装好 element-ui@2.x 以后,首先安装sass-loader npm i sass-loader node-sass -D 2.安装 element-theme npm i ele ...

  8. centos7 python3 pip

    pip of python3 installed is play well with Django and spider.   #安装pip可以很好的使用django和爬虫 wget https:// ...

  9. 自定义GridControl编辑器

    本文版权归博主 惊梦无痕 所有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作.SourceLink 鉴于网上的针对GridControl的一些代码比较凌乱,且功能分散,故将整理过的代码分享出来 ...

  10. 【转载】假设有以下代码 String s = “hello”; 阿里巴巴笔试题

    原文链接点这里 equals 源码如下: 分析: //true equal用于比较两个对象的值是否相同,和内存地址无关