OO Unit2 博客作业

基于度量来分析⾃己的程序结构


自认为自己的架构不算特别复杂,一个电梯类,一个请求队列。代码量也挺少。

复杂度分析

类复杂度:

方法复杂度:



看了idea自带的代码分析,和我原先想的一样。复杂度最高的是电梯类和请求分析类。请求分析类因为要每次更新请求列表,SCAN下一个目的楼层,所以复杂度自然就高。其实我的代码也没有其他东西了。

架构分析

大概的思路如下:
调度器

在这里新请求分为三种

  • 能直达
  • 不能直达,从起点到换乘楼层
  • 从换乘楼层直达目的楼层

如下所示

电梯

非常简单的想法,没有任何优化。最多是作业二的时候,用的不是ALS,而是类似于SCAN的一种算法,但其实性能分也不是很高,作业三只确保了正确性。

改进和重构

本次电梯单元三次作业都没重构。三次作业祖传电梯,没写优化,有很大的改进空间。

架构方面

  • 电梯类可以分成三个子类,继承电梯父类。这样比较OO,但其实我觉得不必要。
  • 请求队列只有一个我觉得可以避免很多同步问题,所以暂时不打算改。
  • 电梯的run方法很长,肯定有设计上的不合理,有代码重复的情况。修改:应该把这部分重复代码另外写一个方法,两次调用。又因为重复之中还有个别语句不同,可以在调用方法的时候传参,然后选择性执行个别语句。我不知道这样写是不是符合Java设计,但现在我只能想到这样处理,但觉得不是很规范。
    将电梯不同的动作分别写成不同的方法,而不是在一个run方法中将所有动作都详细实现。

  • 调度器是否需要写成一个线程?
    在研讨课上,同学们分享了自己的架构,大多数人还是写了调度器线程的,不管是否鸡肋。可能这样比较符合实际,但是我觉得,如果调度器线程真的在负责电梯任务的调度,就应该给他一个线程,否则就没有必要单设线程了。
    我的调度器线程应该可以省略,因为调度工作由电梯自己完成,其实我也没有进行任务调度,请求给三个电梯,然后三个电梯抢着去接人,这也是我只有一个请求队列的后果。

性能优化

  • 电梯提前去换乘层
    需要换乘的人,应该在刚输入的时候,就把他即将要换乘的楼层列入备选目的楼层之一。针对的数据样例:FROM-1-TO-16,可以预先让A上15层,而不是B或者C从1楼把人接到15楼之后,A再行动。
    研讨课上一位同学分享了这个问题的解决思路,他的做法是设置一个buffer,存储这种换乘的后一段接送任务。当电梯没有当务之急的请求,就去执行在buffer中的请求。
  • 空闲电梯去中间等候
    但因为测试数据随机分布。但其实也并不知道数据是怎样分布,可能事倍功半,故本条鸡肋。
  • 预选调度电梯
    每个人进来之后,计算各个可停靠的电梯如果加了这个人,各自会花多少时间去接送。以及以何种顺序接送这个人更省时间。
    但是,基于当前电梯的状态去选择最佳电梯,也只是当前情况下的最佳。而电梯的运行是一个动态的过程而且也在不断加入新的请求,所以可能当前情况下的最佳并不是全局的最佳。
    在研讨课上我问了一位同学,他表示确实存在这样的局面,但是由于我们不能预知未来,所以只能选择当前情况下的最佳。如果不能离线运行,而非要在请求刚进入的时候就调度完毕的话,大概也只能这样了。
    所以我觉得自己三个电梯去抢人这个“不调度的算法”,也不算太差。
  • 贪心算法
    即上了2层回头接1层的人。这个需要比较回头接和送完人之后再回来送这个人之间性能差异,所以需要知道这个人的方向和电梯方向是否一致,以及这个人的起止楼层和电梯的起止楼层比较,权衡的最好方式我认为还是各自计算一下时间。

发现过的BUG

  • 最后一条请求门没关
    应该是在关门之前就结束整个程序了,我知道我用System.exit(0)强制退出可能不太好,应该让每个程序都结束run自动结束进程,然后从main函数退出程序。从讨论区和群里又看到可以用join()函数将main和线程联系起来之类,可能和个人架构有关。在5行代码以内解决这个问题的方法就是开门sleep400,关门sleep0,有点狡猾。
  • 超载
    这个在课下就改了。在人进入电梯之前检测容量。
    但是,如果要加入贪心算法等这些要特地回头接人的算法的时候,如果电梯此时已经满员,就不应该再回头接人,就相当于不应该再继续响应任何请求,包括顺带的和不顺带的。
  • -4层和21层
    超过楼层限制这个问题我没出,大概是没有及时停止电梯运行。
  • 4层到3层,2层到3层
    因为电梯的停靠楼层限制,上下一层还得换乘。在换乘调度的时候分类清晰,路线规划,不能陷入上上下下还到不了终点,或者直接不接人。所以重点在调度要路线清晰,可以不唯一(根据电梯此时方向进行动态调整),但是一定要清晰。
  • CPU超时。
    是轮询的问题,debug方法就是在每个while语句块里加debug打印输出信息,并且用命令行执行,看是哪个while循环偷偷轮询了。多线程我觉得经常会在我自认为不会出现while空跑的地方有很短暂的空跑。

简化问题

我觉得写程序最重要的是简单,思考问题也是。电梯类的设计,请求队列的设计,甚至是退出程序的设计,都可以思考一下可以怎样简化。这样会少很多写代码和debug的时间,我相信就目前的OO作业来说,架构越简单,bug就越少,因为根本无处滋生bug。我的意思并不是修复漏洞的补丁和bug之间的关系,只是说整个架构应该尽可能简化。
一个好的模型很重要。建模的时候不应该陷入“如何实现”的工程细节,而应该站在代码之外,高度抽象概括问题。
那么电梯作业的逻辑就是:电梯获得新请求-》去接-》直达则送达-》不直达则送至换乘层-》换电梯接-》送达。这样一个路线。
剩下的都是工程细节的问题,不在设计环节考虑。

结束程序

曾有同学问我结束程序的模块应该怎么写,我的想法也很简单,就是停止输入+请求队列为空=结束。因为不能轮询,所以设计为:当电梯即将进入等待状态前唤醒检测一次(是否满足停止输入+请求队列为空),若是则结束程序,若不是则检测机制再次进入等待。所以最终结束程序的条件概括为:三个电梯都处于等待状态--》停止输入+请求队列为空。

一个电梯类

本程序中只有一个电梯类,虽然可以写成三个类继承一个电梯父类,但我觉得我们这个题没有太大的必要,因为只有个别数据不同,例如上下速度,停靠楼层,载客量,这些数据都可以用一个私有方法get,没有必要写新的类。

一个请求队列

以及只有一个请求队列,在我构想的模型中,所有的人都在电梯间等待,电梯间里有1/2/3个电梯。对于人来说,人们看到电梯开了门就上,拥挤在一团并没有提前排成三列,也没有精神洁癖非得上哪个电梯。对于电梯来说,电梯只管自己跑楼层,不管载客量多少,人们是直达还是换乘,外面还有多少人,电梯自身不思考这些。
乘客自己需要对自己要去哪负责,而现实中确实如此。乘客上了电梯之后自行决定在哪一层下,或目的楼层,或换乘楼层,然后告知电梯,电梯实际上不知道这个楼层是目的楼层还是换乘楼层,也不需要知道这个。人们若是到达了目的地就从电梯间走出,若是没到目的地就继续待在电梯间里,显然他现在的起始楼层变了。

多线程初探

这单元是第一次写多线程的程序,碰到过一些很迷的状况,但大多是我自己程序别的地方出了bug。多线程就像按下葫芦浮起瓢,有很多东西要同时考虑,但其实在具体实现的时候,在写代码的时候,还是葫芦写完写瓢,瓢de完de葫芦,不可能也没必要一边写葫芦一边写瓢。其实还是一个一个把模块写好的过程。
看了一些大佬对于电梯性能的魔鬼优化,确实很周全,做了我能想到的一切,并且真实实现了,确实很厉害。可能下次作业我也可以稍微加入一些性能优化,有时间的话。

OO Unit 2 电梯调度的更多相关文章

  1. 北航OO第二单元——电梯调度

    三次作业要求简介 特点:目的选层电梯 在电梯的每层入口,都有一个输入装置,让每个乘客输入自己的目的楼层.电梯基于这样的一个目的地选择系统进行调度,将乘客运送到指定的目标楼层. 第一次: 在任意时刻输入 ...

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

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

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

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

  4. OO电梯调度

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

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

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

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

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

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

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

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

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

  9. OO第二单元电梯作业总结

    目录 目录一.第一次作业分析设计策略基于度量分析程序结构二.第二次作业分析设计策略基于度量分析程序结构三.第三次作业分析设计策略基于度量分析程序结构四.分析自己程序的bug五.发现别人程序bug所采用 ...

随机推荐

  1. java eclipse中使用wsdl生成soap 的客户端代码

    项目右键--> new --> other finish完成

  2. ArcGis Python脚本——遍历输出面或折线要素的折点坐标

    有示例要素类如下 经过下面代码处理 #遍历输出面或折线要素的折点坐标 #infc:输入要素类 # code source: https://www.cnblogs.com/yzhyingcool/# ...

  3. ES2015 中的函数式Mixin

    原文链接:http://raganwald.com/2015/06/17/functional-mixins.html 在“原型即对象”中,我们看到可以对原型使用 Object.assign 来模拟 ...

  4. Linux-Shell编程之数组操作

    源码 #!/bin/bash str="Array - Demo Shell"; echo ${#str} #求字符串長度 #定義 arr=('a' 'b' 'c' 'd' 'e' ...

  5. 开发一个项目之npm

    npm (nodejs平台上写的js模块的管理工具  下载.互相依赖等) npm install 本地项目的node_modules文件夹  , -g  npm config prefix 目录eg: ...

  6. 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165237

    2018-2019-2 <网络对抗技术>Exp0 Kali安装 Week1 20165237 安装虚拟机 首先创建虚拟机 创建好虚拟机后,打开虚拟机进行安装.第一步选择Graphcal i ...

  7. RandomAccessFile出现中文乱码问题

    之前程序里调用了RandomAccessFile的writeByte(String str)方法,报文里存在中文的时候出现了乱码 后面换成了 write(byte b[])或writeBytes(by ...

  8. FATAL ERROR: please install the following Perl modules before executing

    运行安装mysql 报错 [root@localhost mysql-mult]# ./scripts/mysql_install_db  --defaults-file=conf/3306my.cn ...

  9. NBIoT三种部署方式【转】

    转自:https://472880.kuaizhan.com/89/34/p441944286fccf2 本文作者:吴老司撩通信 本文来源:EETOP NB-IoT支持在频段内(In-Band).保护 ...

  10. java学习笔记02-Eclipse IDE配置

    Eclipse是java的ide工具,ide是集成开发工具.实际开发中都需要使用ide工具.eclipse下载 java代码在运行时,是需要先进行编译,然后才能运行.可以直接在IDE工具里运行,它会帮 ...