OO第二单元总结
这一单元作业是围绕电梯调度进行展开,并引进了多线程的概念。与第一次作业比较类似,作业难度也是逐渐推进,从最开始的单部电梯先来先服务(傻瓜式调度),到之后的单部电梯可稍带调度,到最后的多部电梯分楼层调度。下面分别说明并分析一下三次作业的设计结构。
第一次作业
作业概述:程序的输入流会不定时随机投放若干用户请求,用户的请求包括出发楼层和目标楼层,电梯没有容量限额,在规定时间上内完成所有请求。
这次作业的意图是让大家对线程有一个初步的认识(因为用户请求不定时投放,电梯强制在线必须要用线程才能搞定),共享对象的加锁保护以及线程之间的同步控制。单论本次作业的难度还是很低的,我大概用了三四个小时就完成了本次作业。
设计策略
由于第一次作业只有正确性要求,没有性能分,所以我也就没费工夫想如何优化调度hhh,就直接写了个先来先服务的模型。尽管电梯很愚蠢,看着有人经过也不捎带一下。。。但是在正确性上有十分充足的保证。
实际上,第一次作业得电梯调度就是最经典得生产者消费者模型,整个代码也就分为了三个部分,两个线程。主线程也就是第一部分用来接收用户请求,也就是生产者,另一部分是共享对象用来存储请求队列,最后一部分是电梯线程用来从请求队列中获取请求,也就是消费者。
代码分析
设计图

各个类得作用请见设计策略。也没什么可具体分析的了。
度量分析


可以看出这次设计的层次还算不错,各个指标都没有特别高的。当然这是因为这次作业比较简单。
Bug分析
分析自己程序的bug: 这次作业没有bug。
分析他人程序的bug: 高工这块没有互测部分,但是也和同学私下互相讨论过,测试方法就是写几个测试样例看看结果是否正确,以及看看代码内部是否有明显的逻辑漏洞。均为发现错误。
第二次作业
作业概述:这次作业和第一次作业基本一样,也是一部电梯,同时没有人数限制。唯一的区别就是要完成捎带调度。当然说是增加了调度算法,但是实现起来还是十分容易的。只需要每次到达一层楼的时候看一眼该楼层是否存在相同运行方向的等待的人。
设计策略
基本和第一次作业一样,同样都是两个线程,分别是主线程读取用户请求,子线程运行电梯。共享队列实际上是内置在电梯中的,但是为了方便理解,我还是单独写了一个共享队列的类,但是并没有做成线程,只是经了一下手立马就发给了电梯的内置队列(自己骗自己hhh)
代码分析
设计图

度量分析


Bug分析
分析自己程序的bug:似乎还是没有bug。。。这次虽然还是没有bug,但是因为有了性能分,所以并不是满分。我也只是实现了指导书中推荐的捎带算法,没有考虑其他更好的优化方法。实在是打不过优化大佬们。。。
分析他人程序的bug:在和其他小伙伴交流的时候还是没有发现什么bug,有的同学是把所有请求都添加到电梯中,也就是不管这个人是向上走还是向下走,你先进来,先和我绕一圈回头我再送你去你的楼层。虽然很不符合实际,但是似乎比常规的捎带方法最终的时间还要短。。也是有点意思。
第三次作业
作业概述:这次作业有了很大的升级,分为了三个电梯,每个电梯可以停留的楼层还不一样,有的人还必须要换乘才能到达指定的楼层。各个电梯的速度也不一样。
设计策略
这次的设计结构不同于上述两次作业,要复杂很多。由于这个有三个电梯也就是有多个消费者,所以并不能像之前那样把共享对象写在电梯里面,而是要有一个调度器对所用请求指定电梯后,在电梯内部再进行二次调度,也就是可稍带调度。所以总体上是有五个线程,一个主线程接收请求,一个子线程作为主控用来处理请求队列的分发,剩下三个是电梯线程,用来处理每个电梯的调度以及电梯的运行。但实际上由于这里有的请求非常的麻烦,需要不同电梯协同工作才能完成,比如说请求要从20->3楼,而只有A电梯能停留20楼,只有C电梯能停留3楼。所以这种情况我的处理办法是先让A电梯停留在一个AC都能停留的楼层,比如说5楼,然后这时把请求发到5楼同时修改成一个新的请求为5->3楼,这样再把这个新的请求发送给主控的共享队列。也就是说除了Main线程是生产者以外,电梯内部也可以生产新的请求。至于是如何调度的,我的调度器十分简单,就是先判断是否有直达电梯,并将请求发给最近的直达电梯。如果没有可用的直达电梯(两种情况,直达满了,或者就是需要中转的)就给一个最近的电梯。电梯到每一层的运输规则都是写死的,比如如果能直达就直达就ok了,但像A电梯不能到3楼,所有通过A想去3楼的就都会送到5楼。显而易见,我这种方式绝对不优,甚至有时候很愚蠢。
代码分析
设计图

度量分析



可见Request类的sendRequest()函数的度量值很高,这是因为里面进行了非常对的if判断,来分类到底要给哪个电梯。
Bug分析
分析自己程序的bug:依旧没有bug。
分析他人程序的bug:我看的大多数小伙伴的代码bug主要集中在程序结束判断上。当然不同人写法不一样,但大体来讲不能简单通过Main线程的输入结束来判断是否要关闭主控线程,必须要等所有的电梯都结束了同时没有输入了才能关闭。
总结
先从课程作业体验上讲一下,总体感觉这一单元的体验要比上一单元好一些,代码写得也顺利很多,最多用一天就都能写完(难道是我进步了???)。
在说说多线程编程的体会吧,总的来讲前两次作业不需要太多的思考,简单加个同步锁就ok了。但是在第三次就了一些更深的感受,首先多线程debug就很不同,单步调试基本没啥用,print会更直接。其次就是加锁的艺术,有的时候全部加上锁肯定没问题,但是性能会下降很多,但是如果减少锁的范围可能又会出现不同步带来的bug,所以需要好好权衡和设计这块。
最后感谢老师和助教的帮助和指导!
OO第二单元总结的更多相关文章
- oo第二单元作业总结
oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...
- OO第二单元优化博客
OO第二单元优化博客 第五次作业没有性能分,但是,我在这一单元的宗旨就是写一个日常生活中 最常见的那种电梯,所以第五次我没有写傻瓜电梯,而是直接写了个\(look\),和第六次基本相同. 总计一下lo ...
- 【OO学习】OO第二单元作业总结
OO第二单元作业总结 在第二单元作业中,我们通过多线程的手段实现了电梯调度,前两次作业是单电梯调度,第三次作业是多电梯调度.这个单元中的性能分要求是完成所有请求的时间最短,因此在简单实现电梯调度的基础 ...
- OO第二单元小结
OO第二单元小结 一.三次作业代码分析. 1.第一次作业 第一次作业是单部电梯的傻瓜调度,由于其过分傻瓜,所以第一次作业我只有两个类,一个main,一个电梯,main类负责不断从输入流中读取命令,如果 ...
- OO第二单元多线程电梯总结
OO第二单元多线程电梯总结 第一次作业 设计思路 Input为输入线程,负责不断读取请求并将读到的请求放入调度器中. Dispatcher为调度器,是Input线程和Elevator线程的共享对象,采 ...
- 电梯也能无为而治——oo第二单元作业总结
oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...
- 2020北航OO第二单元总结
2020北航OO第二单元总结 前言 本单元考察基于多线程的电梯调度问题,成功让我从一个多线程小白到了基本掌握了使用锁来控制线程安全的能力,收获颇多(充分体验了迷茫地de一个又一个死锁bug的痛苦). ...
- OO第二单元——多线程(电梯)
OO第二单元--多线程(电梯) 综述 第二单元的三次联系作业都写电梯,要求逐步提高,对于多线程的掌握也进一步加深.本次作业全部都给出了输入输出文件,也就避免了正则表达式判断输入输出是否合法的问题. 第 ...
- OO第二单元作业总结【自我反思与审视】
第二单元作业的完成史,就是一部心酸的血泪史…… 多线程的出现为我(们)打开一片广阔的天地,我也在这方天地摸爬滚打,不断成长!如果说第一单元之前还对Java语法有所了解的话,那么这单元学习多线程则完全是 ...
- OO第二单元(电梯)单元总结
OO第一单元(求导)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉理解和掌握多线程的思想和方法.这个单元以电梯为主题,从一开始的最简单的单部傻瓜调度(FAFS)电梯到最后的多部 ...
随机推荐
- 报文ISO8583协议
本人刚接触金融IT行业,对报文ISO8583协议也是刚刚了解,看了篇文章,个人觉得写得很好,特此分享如下: 如果单纯的讲IS08583那些字段的定义,我觉得没有什么意思,标准中已经对每个字段解释的非常 ...
- Spark学习之Spark Streaming
一.简介 许多应用需要即时处理收到的数据,例如用来实时追踪页面访问统计的应用.训练机器学习模型的应用,还有自动检测异常的应用.Spark Streaming 是 Spark 为这些应用而设计的模型.它 ...
- TensorFlow从1到2(九)迁移学习
迁移学习基本概念 迁移学习是这两年比较火的一个话题,主要原因是在当前的机器学习中,样本数据的获取是成本最高的一块.而迁移学习可以有效的把原有的学习经验(对于模型就是模型本身及其训练好的权重值)带入到新 ...
- 补习系列(20)-大话 WebSocket 与 "尬聊"的实现
目录 一.聊聊 WebSocket 二.Stomp 是个什么鬼 三.SpringBoot 整合 WebSocket A. 引入依赖 B. WebSocket 配置 C. 控制器 D. 前端实现 四.参 ...
- Docker最全教程——Redis容器化以及排行榜实战(十三)
前言 容器教程的路还很长,笔者尽量根据实践来不断地完善.由于在编写的过程中还会有完善和补充,后续可能会以番外来补充. 接下来会分享TeamCity.树莓派等内容,节奏可能会有点跳脱. 另外,长沙.NE ...
- asp.net core系列 55 IS4使用Identity密码保护API
一.概述 OAuth 2.0资源(web api)所有者密码授权,允许客户端(Client项目)向令牌服务(IdentityServer项目)发送用户名和密码,并获取代表该用户的访问令牌.在官方文档中 ...
- Python进阶:设计模式之迭代器模式
在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...
- c# 事件的订阅发布Demo
delegate void del(); class MyClass1 { public event del eventcount;//创建事件并发布 public void Count() { ; ...
- ORM之轻量级框架--Dapper
一.什么是Dapper? Dapper是一款轻量级Orm框架,它是属于半自动的,它和Entity Framework和NHibernate不同,它只有一个单文件,没有很复杂的配置,如果你喜欢原生Sql ...
- Promise(避免金字塔回调)
前后端分离开发,前端通过接口获取数据,但是有的页面不止一个接口,就会出现金字塔回调,可以通过 Promise 封装请求. request-data.js: function reqData(postu ...