第五次作业分析

1.设计策略

  调度器采用单例模式,内部设请求队列,对请求队列的一切操作(查、增、删)都在调度器内完成,且都要求串行,从而确保线程安全。接收器和电梯是两个线程:接收器接受请求调用调度器来存入请求队列,接受器关闭时通知调度器;电梯调用调度器来获得请求,电梯从调度获得空请求且查询到接受器关闭时停止运行。

2.度量分析

(1)复杂度矩阵

方法复杂度:

类复杂度:

由于这一次作业是简单的单电梯傻瓜调度,所以方法和类复杂度都比较低。

(2)类图

(3)协作图

3.bug分析

没有bug。

第六次作业分析

1.设计策略

与上次作业相比,本次作业仅仅增加了捎带,故整体策略不变,仅改变电梯调度的算法为扫描算法且增加捎带功能。

 由于在调度器,我们只关注乘客的出发楼层和目标方向,而在电梯内,只关注乘客的目标楼层。所以可以将调度器中的请求队列分割为上行请求队列和下行请求队列以及乘客目标楼层图,在电梯内新增楼层到达图:

上行请求队列:每一层有哪些乘客要上行;

下行请求队列:每一层有哪些乘客要下行;

乘客目标楼层图:每一位乘客要在哪一层出电梯;

楼层到达图:每一层有哪些乘客要出电梯。

 实现捎带:

 电梯到达每一层时向调度器发送捎带请求,调度器将对应方向请求队列中该层的乘客的目标楼层图返回给电梯,电梯捎带这些乘客,将他们加入对应楼层到达图对应楼层的乘客列表。

 实现扫描算法:

 电梯属性中新增方向和目标楼层。

电梯中没有乘客(当前楼层为目标楼层),选择主请求(新的目标楼层)时:

①选择方向与电梯当前方向一致,且出发楼层在电梯当前楼层的当前方向上的最近请求,若存在这种请求:

若该请求在当前楼层,则将该乘客目标楼层设为电梯目标楼层;

否则将该请求出发楼层作为电梯目标楼层。

②若不存在①中那种请求,则选择方向与电梯当前方向相反,但出发楼层在电梯当前楼层的当前方向上的最远请求,若存在这种请求,将电梯方向取反:

若该请求在当前楼层,则将该乘客目标楼层设为电梯目标楼层;

否则将该请求出发楼层作为电梯目标楼层。

③若不存在②中那种请求,则选择方向与电梯当前方向相反,且出发楼层在电梯当前楼层的当前方向反方向上的最近请求,若存在这种请求,将电梯方向取反:

若该请求在当前楼层,则将该乘客目标楼层设为电梯目标楼层;

否则将该请求出发楼层作为电梯目标楼层。

④若不存在③中那种请求,则选择方向与电梯当前方向相同,但出发楼层在电梯当前楼层的当前方向反方向上的最远请求,若存在这种请求:

将该请求出发楼层作为电梯目标楼层。

⑤若不存在④中那种请求,说明当前没有请求,若接收器关闭则停止运行电梯,否则等待请求到来。

每一次捎带后:

若电梯上行,存在乘客的目标楼层中最高的在电梯目标楼层更高层,则将该楼层设为电梯目标楼层;

若电梯下行,存在乘客的目标楼层中最低的在电梯目标楼层更低层,则将该楼层设为电梯目标楼层。

2.度量分析

(1)复杂度矩阵

方法复杂度:

类复杂度:

扫描调度算法的实现稍微有些复杂,乘客进入电梯和更新目标楼层的方法要遍历对应的捎带图,导致电梯循环复杂度稍高。

(2)类图

 

(3)协作图

4.bug分析

没有bug。

第七次作业分析

1.设计策略

本次作业为多电梯调度,每个电梯有对应的可达楼层。

我采用的是静态分配请求的策略。新增一个分配器,每个请求刚刚收到就规划好其需要搭乘的第一部电梯及对应的出电梯的楼层,将其分配给对应电梯的调度器,每个电梯由自己的独立的调度器根据自己内部的请求进行独立调度,每个请求出电梯后若未到达目标楼层再新生成请求提交到分配器。

这种策略简单但在一些情况下效率可能不高。

2.度量分析

(1)复杂度矩阵

方法复杂度:

类复杂度:

除了捎带和扫描算法导致的复杂度问题,这次的分配器为每一个可能的x层到y层的请求选择第一次搭乘的电梯和出电梯楼层的方法也较为复杂,另外在主方法中手动创建每个电梯的可达楼层列表使用不少循环导致主方法循环复杂度较高。

(2)类图

(3)协作图

4.bug分析

由于开始写的时间太晚,导致压着时间点完成,最后忙中出错,没有初始化时间戳,这一次作业无效了。

SOLID原则

1.SRP(单一责任原则)

个人感觉三次作业每个类的责任都比较单一,最后一次可能应该写一个类来创建电梯,不应该直接放在主方法中。

2.OCP(开放封闭原则)

 第五次作业的调度器接收请求的方法在第六次进行了重写,因为改变了请求队列的存储方式。

3.LSP(里氏替换原则)

没有父子类,不讨论。

4.ISP(接口分离原则)

 三次作业的接口设置的都较为合理,没有这方面的问题。

5.DIP(依赖倒置原则)

三次作业的类间依赖都是自然合理的,没有这方面的问题。

总结与心得

多线程编程的debug是一个头疼的大问题,所以一定要从一开始就小心谨慎,尽量避免程序中出现bug。

另外,最重要的:

 永远不要拖延!

OO第二单元总结——多线程电梯的更多相关文章

  1. 2019年北航OO第二单元(多线程电梯任务)总结

    一.三次作业总结 1. 说在前面 对于这次的这三次电梯作业,我采用了和几乎所有人都不同的架构:将每个人当作一个线程.这样做有一定的好处:它使得整个问题的建模更加自然,并且在后期人员调度变得复杂时,可以 ...

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

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

  3. OO第二单元作业——魔鬼电梯

    简介 本单元作业分为三次 第一次作业:第一次作业要实现单部简单电梯,停靠所有楼层,无载客容量,性能分考量电梯运行时间. 第二次作业: 第二次作业实现多部电梯,电梯数量由初始化设定,每部电梯都停靠所有楼 ...

  4. oo第二单元作业总结

    oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...

  5. OO第二单元多线程电梯总结

    OO第二单元多线程电梯总结 第一次作业 设计思路 Input为输入线程,负责不断读取请求并将读到的请求放入调度器中. Dispatcher为调度器,是Input线程和Elevator线程的共享对象,采 ...

  6. OO第二单元——多线程(电梯)

    OO第二单元--多线程(电梯) 综述 第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深.本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题. 第 ...

  7. 电梯也能无为而治——oo第二单元作业总结

    oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...

  8. OO第二单元电梯线程系列总结作业

    电梯系列第一次作业 功能描述: 傻瓜电梯无需考虑超载捎带 线程模式: Producer-Consumer Pattern 思路: 第一次作业是一个傻瓜电梯,分别有一个生产者生成电梯指令(也就是Inpu ...

  9. 【OO学习】OO第二单元作业总结

    OO第二单元作业总结 在第二单元作业中,我们通过多线程的手段实现了电梯调度,前两次作业是单电梯调度,第三次作业是多电梯调度.这个单元中的性能分要求是完成所有请求的时间最短,因此在简单实现电梯调度的基础 ...

随机推荐

  1. DotNetCore跨平台~为debain系统添加阿里云加速

    回到目录 直接把它阿里云的镜像覆盖到原来的/etc/apt/sources.list文件 cat > /etc/apt/sources.list << EOF deb http:// ...

  2. SpringBoot实用小知识之Maven中dependencys和dependencymanagement区别

    利用pom管理引用包时,如果是单项目的话就直接在dependencies引用了,若有一个大工程项目里面包含多个子模块,则为了所有项目模块包的版本统一和好管理,则需要用到dependencyManage ...

  3. [个人网站搭建]·Django增加评论功能(Python3)

    [个人网站搭建]·Django增加评论功能 个人主页--> https://xiaosongshine.github.io/ 个人网站搭建github地址:https://github.com/ ...

  4. KOA中间件的基本运作原理

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 在中 ...

  5. C# WebRequest.Create 锚点“#”字符问题

    背景 在与后台API接口对接时,如将网页Url作为参数请求数据时,如果是锚点参数,则会丢失. 锚点参数 请求通过WebRequest.Create创建一个WebRequest: var uri = & ...

  6. 简述ADO.NET的连接层

    前面曾提到过ADO.NET的连接层允许通过数据提供程序的连接.命令.数据读取器对象与数据库进行交互.当想连接数据库并且使用一个数据读取器对象来读取数据时.需要实现下面的几个步骤 * 创建.配置.打开连 ...

  7. while,for,if输入账号密码判断(还请各位大牛能够优化,本人刚学习一周)

    AccountNumber1 = [] password1 = [] flag = True while flag: num = 0 a = 1 print('-----------这是个欢迎界面-- ...

  8. 如何利用GitHub设计一个炫酷的个人网站(含代码)

    1.在开始制作之前我们先预览一下我的网站吧! 1.方式一: 由于是手机版的所以用手机访问下面的链接体验比较好一点: https://tom-shushu.github.io/MyWeb.github. ...

  9. 2018-07-10 为Chrome和火狐浏览器编写扩展

    由于扩展标准的逐渐一致, 现在同一扩展代码库已经有可能同时用于Chrome和火狐. 下面是一个简单的工具栏按钮和弹窗(尚无任何实际功能): 代码库地址: nobodxbodon/suan1 所有代码: ...

  10. Android Fragment碎片

    什么是碎片? 碎片(Fragment)是一种可以嵌入在活动当中的UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常广泛.可以把Fragment当成Activity一个界面的一 ...