前言
这一单元关于线程安全的作业结束了,在助教提供的接口的帮助以及老师提供的设计模型的指导下,这三次作业还是相对轻松地完成了,中间也没有出现什么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第二单元作业——魔鬼电梯
简介 本单元作业分为三次 第一次作业:第一次作业要实现单部简单电梯,停靠所有楼层,无载客容量,性能分考量电梯运行时间. 第二次作业: 第二次作业实现多部电梯,电梯数量由初始化设定,每部电梯都停靠所有楼 ...
随机推荐
-
快速开发Grunt插件----压缩js模板
前言 Grunt是一款前端构建工具,帮助我们自动化搭建前端工程.它可以实现自动对js.css.html文件的合并.压缩等一些列操作.Grunt有很多插件,每一款插件实现某个功能,你可以通过npm命名去 ...
-
android百度地图相关
1.如果有报错Multiple dex files define Lcom/baidu/android/bbalbs/common/a/a一般是有重复jar包. 2.百度地图开发调试的应用程序正 ...
-
BibTex插入Reference
1. 在tex文件中加入: \bibliographystyle{plain} %这是格式 \bibliography{reffile} % reffile.bib是reference的文件 2 ...
-
FTS抓包看AVDTP
1.概述 测试过程为打开Audio连接,没有听音乐,人后断开Audio连接,主要目的是为了测试AVDTP的工作流程. 2.Frame分析 首先贴出抓取的关于AVDTP的包: 在L2CAP ...
-
内核中读取UTC时间
记录这个知识点的原因是因为项目中需要保存充电日志,因此,趁着这个机会,深入了解一下Linux的时间系统. UTC:(Universal Time Coordinated) 协调世界时的缩写 ...
-
Java的浮点数
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/5160771. ...
-
【转】repo 的一些用法和理解-不错
原文网址:http://blog.csdn.net/yasin_lee/article/details/5975068 repo的用法(zz) 注:repo只是google用Python脚本写的调用g ...
-
重启oracle数据库的一次操作命令和alter日志。
今天重启oracle数据库的命令和alter日志: oracle@NMSSERVER1:~> sqlplus '/as sysdba' SQL*Plus: Release 11.2.0.3.0 ...
-
Python使用Selenium/PhantomJS
安装selenium: 1 pip install selenium 安装PhantomJS: 1 2 3 4 https://bitbucket.org/ariya/phantomjs/downlo ...
-
cms STW 的两个阶段
CMS在初始标记和重复标记阶段会停顿