OO第二单元作业分析
前言
这一单元关于线程安全的作业结束了,在助教提供的接口的帮助以及老师提供的设计模型的指导下,这三次作业还是相对轻松地完成了,中间也没有出现什么bug,可能就是因为简单的逻辑不容易出错吧,可惜两次都由于性能分与a组失之交臂,或许在后续作业中还是应该多在性能优化下做一些工作。
第一次作业
设计思路
这次参考了老师所给的生产者消费者问题,主要设计了电梯类,控制器类,输入器类,主类,电梯类只负责向调度器请求指令,并根据接收到的指令进行上下楼接送人操作,输入器类只负责接受指令并向调度器塞入指令,控制器类负责按照时间顺序从输入器抓取指令,并发送给电梯,这里采用的是傻瓜算法,即做完一条指令再发送下一条指令。同时控制器类还负责电梯类的线程结束。这里让线程安全结束的方法是,输入器类只要接收到文件结尾就结束输入 器线程,并设置一个布尔变量作为输入结束的标志,当输入结束并没有指令继续存在时,电梯线程结束。
基于度量来分析自己的程序结构
程序结构
正如设计思路中所说,采用生产者消费者模式:电梯作为消费者,输入器作为生产者,调度器作为托盘,就构成了整个程序的结构
度量分析
可以看到由于采用的是是简单的傻瓜调度,所以这个程序各个类之间的耦合度非常低,相对来说耦合高一点儿的只有调度器和电梯、调度器和输入器之间关于指令传输的方法。
其他
总的来说这次作业难度不大,主要精力花费在如何在各种输入条件下平稳结束各个进程,采取的方式如前文所说,通过设置表示输入结束以及表示指令队列为空的变量,作为break的条件,跳出while循环,从而结束线程
第二次作业
设计思路
这次仍然要求的是一部电梯,要求电梯能够实现捎带算法或者其他更快的算法。由于电梯的请求到来的情况具有不确定性,导致各种算法都存在性能十分差的极端情况,所以在写这次作业的时候果断选择了按照指导书上的捎带算法:主要是定义了主请求、捎带条件
主请求是:当电梯请求队列不为空时,主请求是到达电梯请求队列时间最长的请求,当电梯请求队列为空的时候,主请求是到达调度器时间最长的请求
捎带条件是:当前主请求与该请求的目的地处于电梯当前位置的同一侧,即可以成为捎带请求
为了能够不混淆会令主请求的人乘坐时间过长的捎带请求,我在程序中规定:电梯只能添加满足捎带条件并且出发楼层与电梯当前位置相同的捎带请求
这样的话电梯的工作流程就是:
主请求为空时:向调度器申请主请求,并去接主请求发出者
每到达一层楼,判断是否需要停留(有无人上下电梯、有无当前楼层可添加的捎带请求)
每当主请求下电梯时就更新主请求
当电梯为空时又重复第一步
同时需要注意的是由于现在一个电梯可装载多个请求,为了避免电梯在装到人之前就下人的情况:
我为每个人设置了状态,上电梯之前的“not in”,上电梯之后是“already in”从而避免了bug出现。
基于度量来分析自己的程序结构
程序结构
由于这次的电梯本质上只需要更改调度器向电梯派发指令的策略,添加判断是否应该停靠、派送捎带请求的方法,所以整个程序总体上结构没有太大变化,代码也基本沿用第一次作业的代码,只做了少量修改。
度量分析
由于基本沿用了上一次作业的代码所以各个类之间的耦合度还是比较低,唯一高一些的是pusubcmd方法,这是由于这个方法要求调度器能够知道电梯当前的位置即已经装载了的指令的情况,所以与电梯类的耦合度较高。
其他
总的来说这次作业难度不大,主要精力花费在如何设计捎带算法的实现,让电梯运行的时候面对各种指令情况不会出现吃人、造人、不停开关门的bug,解决的方法是:
只装载电梯当前位置的捎带指令。
为人设置是否进入电梯的变量。
第三次作业
设计思路
这次要求能够支持三部电梯,并且对电梯定义了运动速度,容量,以及可停靠楼层。难点在于根据每个电梯的可停靠楼层,将无法一次乘坐到达的请求,进行拆分,从而到达。
我采取的策略是:通过逐层分析,所有不能一次到达的请求,都能拆分成两次到达,所以我的拆分策略是拆为出发楼层到离当前最近的中转楼层与从中转楼层到目的楼层。
同时由于拆分后的后半部分指令必须在前一半指令结束后才能执行,所以我采取的策略是将其放入一个暂不可执行队列,当前半部分执行完成后,发送信号将后半部分加入可执行队列。
至于运动速度、容量、可停靠楼层等,都可以通过在电梯类中增加相应的成员变量,与判断条件来实现。
同时这次仍采用和第二次一样的捎带算法。
基于度量来分析自己的程序结构
程序结构
除了增加与指令拆分相关的代码与容量速度等新成员变量,整个程序总体上结构没有太大变化,基本沿用第二次作业的代码,只做了少量修改。
度量分析
这一次的代码耦合情况就不像前两次那么令人乐观了,可以看到又四个方法爆了红:
可以看到向电梯发送指令的两个方法pushmiancmd与pushsubcmd的模块复杂度和循环复杂度都较高,这是由于两者在向电梯发送指令前都需先对调度器内部是否还存在符合各电梯要求的指令进行判断,然后根据电梯可去楼层集判断可否推送该指令,最后还需遍历更新当前调度器内符合各电梯可去楼层集的指令状况。所以需要频繁访问电梯的位置信息、可去楼层集、是否超载,以及循环判断指令情况,所以导致这两项复杂度过高。想要解决这一办法可考虑将这两个方法中的部分代码另写代码封装起来。
同时loadcmd的循环复杂度较高,这是由于我在这部分实现了电梯指令的拆分,由于我是暴力枚举的所有拆分情况,所以判断层数多,循环复杂度很高,可以考虑实现一个一般化的拆分方法,不过可能性能就没有暴力枚举的最佳拆分那么好。
其他
这次的难点在于指令拆分,坑点在于指令拆分后,后半部分指令必须等前半部分执行完后才能进入队列,同时考虑是否已经执行完所以指令时必须考虑被放入暂不可执行队列的指令,否则可能会出现电梯提早被kill的情况。
分析自己的bug
由于采用的都是指导书给出的算法和模型,并且在处理时模拟了真实电梯的各种行为而不是只输出结果,所以这三次作业没有被测出bug。可见简单的算法加贴近实际情况的模拟会使代码十分可靠。
找他人bug的策略
这次找他人bug的策略主要是首先提交自己在写代码过程中出现的bug,看他人是否犯了同样的错误,其次是针对于线程安全可能出现的常见问题,比如不能平稳结束、提前结束等进行测试。此后采用的是选取两三份代码风格不佳的代码,阅读分析其思路,然后反向找逻辑错误。可惜由于这几次在的组都是属于,简单思路与实现,导致代码逻辑显得坚不可摧,所以找bug的效果并不太好。
心得与体会
事实证明,简单明了的算法与模拟现实生活的思路能够构造非常可靠的代码,这也是这几次没出bug的原因。只是可惜,由于性能的缘故,后两次作业的分组情况都不是很理想,后续可能考虑在保证可靠性的情况下,采取一些高性能但复杂的算法,来挑战自己!
OO第二单元作业分析的更多相关文章
- 【OO学习】OO第二单元作业总结
OO第二单元作业总结 在第二单元作业中,我们通过多线程的手段实现了电梯调度,前两次作业是单电梯调度,第三次作业是多电梯调度.这个单元中的性能分要求是完成所有请求的时间最短,因此在简单实现电梯调度的基础 ...
- 电梯也能无为而治——oo第二单元作业总结
oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...
- OO第二单元作业总结【自我反思与审视】
第二单元作业的完成史,就是一部心酸的血泪史…… 多线程的出现为我(们)打开一片广阔的天地,我也在这方天地摸爬滚打,不断成长!如果说第一单元之前还对Java语法有所了解的话,那么这单元学习多线程则完全是 ...
- oo第二单元作业总结
oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...
- OO第二单元作业小结
前言 转眼已是第九周,第二单元的电梯系列作业已经结束,终于体验了一番多线程电梯之旅. 第一次作业是单电梯的傻瓜调度,虽然是第一次写多线程,但在课程PPT的指引下,写起来还是非常容易:第二次作业是单电梯 ...
- 电梯模拟系统——BUAA OO第二单元作业总结
需求分析 官方需求 本次作业需要模拟一个多线程实时多电梯系统,从标准输入中输入请求信息,程序进行接收和处理,模拟电梯运行,将必要的运行信息通过输出接口进行输出. 本次作业电梯系统具有的功能为:上下行, ...
- 你电梯没了—OO第二单元作业思考
写在前面 这三次电梯调度作业,主要是学习多线程并行操作,对于各个线程的时间轴的把握,互相的配合与影响,通过使用锁来解决访问冲突等方面. 个人在学会Thread相关操作之外,写出来一些奇怪结构的诡异操作 ...
- 北航OO第二单元作业总结(2.1~2.3)
在经过第一单元初步认识面向对象编程思想后,本蒟蒻开始了第二单元--多线程部分的学习.本单元的作业是构造符合条件的"目的选层电梯"模型,自行设计调度算法,进行合理调度,完成所有乘客的 ...
- OO第二单元作业——魔鬼电梯
简介 本单元作业分为三次 第一次作业:第一次作业要实现单部简单电梯,停靠所有楼层,无载客容量,性能分考量电梯运行时间. 第二次作业: 第二次作业实现多部电梯,电梯数量由初始化设定,每部电梯都停靠所有楼 ...
随机推荐
- POJ - 2777——Count Color(懒标记线段树二进制)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 53639 Accepted: 16153 Des ...
- python学习博客地址集合。。。
python学习博客地址集合... 老师讲课博客目录 http://www.bootcdn.cn/bootstrap/ bootstrap cdn在线地址 http://www.cnblogs. ...
- jmeter如何链接数据库并拿到相应值用到请求中
很久以前学习了jmeter如何使用数据库连接并请求相应值.jmeter如何上传文件 结果现在忘记了很多...,现在重头学习一遍,所以说 还是边学边记录,那天忘记了 ,自己看看笔记 分步骤来写 1.数据 ...
- 2D 加速图形界面开发源代码亲写 想买来学习得加qq 313244484 20万当前代码,完整400万包写完
#include "StdAfx.h" #include "GUIFrame.h" #include <stdlib.h> #include < ...
- JavaScript 获得客户端IP
Below are all the free active IP lookup services I could find and the information they return. If yo ...
- this.$nextTick()作用
当data中的某个属性改变的时候,这个值并不是立即渲染到页面上,而是先放到watcher队列上(异步),只有当前任务空闲的时候才会去执行watcher队列上的任务.所以导致,改变的数据挂载到dom上会 ...
- SmartBinding与kbmMW#1
即将发布的kbmMW,实现了SmartBinding,SmartBinding的设计目标是: 必须易于使用 必须最小化或完全删除锅炉板代码.(你看到这里的趋势了吗?... kbmMW从那时开始就是为了 ...
- Java学习NO.4
学习内容如下: 数组的概述与特征 概述: 它是具有相同数据类型的一组数据的集合 存储在数组中的数据我们称之为数组元素,可通过“数组名[下标]”的方式进行访问,下标也就是索引,从0开始,且负数索引是无效 ...
- MySQL中查询、删除重复记录的方法大全
查找所有重复标题的记录: select title,count(*) as count from user_table group by title having count>1; SELECT ...
- Sublime Text 3(3207)安装
Sublime Text 3207 下载 官网地址: Sublime Text 下载需要的类型 安装插件 安装插件管理器: 打开Sublime,点击Tools => Install Packag ...