OO_Unit2_Summary
经过三周的自己电梯瞎设计,下次坐电梯想我想的可能就不是如何优化调度算法,而是千万别把自己死锁在电梯里了(手动狗头)
一、设计策略
1. 需求分析:
- 作业一:单部多线程可稍带电梯,一部电梯,固定楼层,不限载人数,性能基准为ALS电梯
- 作业二:多部多线程可捎带电梯,不定电梯数,固定楼层,限制载人数
- 作业三:多部多线程可捎带电梯,动态增加电梯,楼层、运行时间、最大载人数为不同的固定值
2.设计分析:
终于体会到迭代的舒服之处了!!!
此三次作业基本一脉相承,始终坚持生产者-消费者模式要求,坚持WorkerThread模式要求,坚持多线程安全性最先的要求,成功的完成了迭代式的三次电梯作业。
一共四个线程,主线程用来启动输入线程和调度器线程,调度器线程中进行启动多部电梯线程,通过一个共享变量将输入线程和调度器线程联系起来构成生产者-消费者模式,调度器内部多个共享变量分别和各部电梯形成生产者-消费者模式。输入线程只管输入数据并将其放入主队列中,调度器线程只管将需求从主队列中取出并按一定的策略分配进各个电梯的外部需求队列中。电梯线程只管依据既定的稍带策略将外部需求队列中的请求取入内部队列中并完成既定运送。(在第三次作业中,由于有了换乘的存在,所以电梯还需要将out的需换乘的乘客重新放入主队列中,当做新的需求处理)
3. 调度策略
电梯自身的策略:LOOK算法,既简单而且效率还不错。(ps:由于自己第一次作业时魔改了一下LOOK算法,结果发现性能还不如纯LOOK算法性能高orz)
调度器策略:第一次作业,单部电梯,无需在此调度。第二次作业,经过多次魔改调度算法后对比发现,单纯的依据哪部电梯的队列需求最少最优的分配策略,性能更稳定并且更高,(优化点,可以采取手段让电梯自行争抢,而并不提前绑定电梯)。第三次作业,同样经过多次魔改调度之后发现,单纯依据各种类电梯的统一需求队列中的需求最少最优的方案,真的真的真的性能最高,同类型电梯共用一个需求队列,自行争抢,毕竟此次性能值包括了乘客总花费时间和电梯运行时间。
我真的不太明白,每次迭代之初修改调度算法时偷懒用的最少最优的调度,竟然比之后处心积虑修改的调度性能更高。难道这就是传说中的大道至简?
4. 死锁问题
很不幸,三次作业我都出现了死锁问题,但是又很幸运的是,这些问题在提交中测之前都发现了(笑脸.jpg)。原因分析为,我在多线程中采用的是synchronize块在需要时再锁对象的方法,随意经常导致锁的交叉需求问题,进而程序一直相互忙等状态。我采取的方法是,理论分析。列出所有有锁的地方,挨个分析互锁的可能性并进行修改。
5. 第三次作业的可扩展性分析
输入线程部分只需根据输入进行解析扩展即可,调度器线程只需根据电梯的要求扩展变化和代替共享的队列以及修改调度算法即可(调度算法虽未单独抽象为一个类,但是已被简化为一个函数,故修改应该也方便),电梯可根据要求修改固有属性即可。
二、SOLID分析
SPR--单一职责原则:软件组件(函数、类、模块)必须专注于单一的任务(只有单一的职责)
我的输入类,调度类和电梯类都只专注与输入,调度分配和电梯运行三个功能,所以我认为满足了此原则。
OCP--开/闭原则:对扩展开放,对修改关闭
由于调度类中的调度算法并没有抽象出一个类,所以在迭代时难免会对调度类产生修改。以及电梯的属性变化,也会使我直接修改源代码,所以此原则不太符合。
LSP--替换原则:子类型可以替代其对应的基类型
由于电梯都是统一建模通过构造参数来创建新的电梯,故本次作业并未涉及继承部分。
ISP--接口隔离原则:将大而全的接口拆分成特定的客户端接口
作业中并未用到接口。
DIP--依赖倒置原则:抽象不应该依赖于细节,细节应该依赖于抽象
电梯类由于是统一建模,具体细节由统一模型的构造参数决定,所以我觉得一定程序上符合此原则。
三、基于度量分析
第一次作业:
第二次作业
第三次作业:
(由于IDEA更新,metrics插件无法使用,故根据记忆以及手动得出以下分析)
三次作业中的run方法好像复杂度都有点高,应该是方法抽离不完全所致
其中第三次作业中Person类的复杂度尤其高,由于我在Person类中case打表进行决定是否换乘,故复杂度极高(争取以后能用算法解决的,我都能够不打表)
四、分析自己程序的bug
此三次作业中,强测和互测均为出现bug,结果归功于我的评测机和手动分析死锁情况,在中测结束之前找出了所有的问题。(由于第一部分已分析了死锁的问题,故在此不再赘述)
五、互测策略
此次多线程互测相比上一单元的互测来说,评测机要求更高,自己写定点投放程序,自己写逻辑判断程序。(ps:我的第一次评测机竟然连到达0层的bug都没测出来,tcl)
其次,由于过分的相信评测机,所以我基本采用的都是黑盒测试,极少手动构造样例,所以三次互测中基本没有收获(除了最后一次,有同学对X1X2X3以外的电梯名称报错,才找到了一个bug)
最后,多线程的独有特性,即使在自己的评测机上出错,在课程组的评测机上也不一定会错;当然自己评测机不会出错的例子,课程组的评测机上也不一定不会出错(当然我没遇到该种样例hhh)
六、心得体会
多线程的锁真的是一个艺术的东西,多了会把自己锁住,少了就会出现莫名其妙的错误,当然锁自己也是有可能的。多线程安全必须慎之又慎,以及多多动手理论分析一下,没有自己解不开的锁(如果有,那就砸烂换把锁)。
(总结起来就是,多线程的安全就是要么我锁我自己,要么就在玄学的世界里畅游,当然大佬都是掌控一切,恰到好处的放锁)
设计原则部分,由于在作业进行中,课上依次讲解了生产者--消费者模式和WorkerThread模式,所以这三次作业的总的框架展开,细节和具体实现通过自己的想法即可。
不得不说经过这三次作业的训练,我加深对多线程经常出现玄学bug和死锁的安全性问题的理解,以及对生产者--消费者和WorkerThread模式的掌握和熟练。实在是收获颇丰。
以及,自我测试和互测的时候一定要黑盒白盒一起上啊,不能偷懒.jpg。
OO_Unit2_Summary的更多相关文章
随机推荐
- 12月15日BGV币行情分析
今日,DeFi市场格外精彩.各主流概念币种走势出现了涨跌各半的两极态势.笔者认为,由于并没有总体可以利好DeFi市场的基本面因素,所以各DeFi概念币种的涨跌态势,还是与各自的基本面和技术面走势相关. ...
- sql server 局域网与公网上的发布与订阅
一台局域网的服务器,可以访问公网. 一台云端的服务器. 要求:将局域网中的服务器部分数据库同步到云端的服务器上. 配置情况: win server 2012 是发布服务器. win server 20 ...
- 百度 Apollo无人车平台增加传感器
https://github.com/ApolloAuto/apollo/issues/1649 如果想加入一个新的传感器不是百度官方推荐的传感器到Apollo平台做法: First you can ...
- JavaScript 中的执行上下文和执行栈
JavaScript - 原理系列 在日常开发中,每当我们接手一个现有项目后,我们总喜欢先去看看别人写的代码.每当我们看到别人写出很酷的代码的时候,我们总会感慨!写出这么优美而又简洁的代码的兄弟到 ...
- Socket实现简单聊天
服务端: package main.java.com.socket_dome; import java.io.IOException; import java.io.InputStream; impo ...
- 2021-2-27:Linux 下如何优化 Java MMAP 写入
主要是调整 pdflush 相关参数. 在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到 ...
- C#测试--内部类测试
C#测试--内部类测试 在被测试的代码库的AssemblyInfo.cs中添加"[assembly: InternalsVisibleTo("UnitTest项目名称") ...
- Innodb的存储及缓存
参考[mysql技术内幕] 一.mysql体系结构和存储引擎 1.数据库与数据库实例 数据库:物理操作系统文件或者其他文件组成的集合: 数据库实例:有数据库后台进程/线程和一个共享内存区域组成. 数据 ...
- 更换 grub 主题
默认的 grub 界面比较简陋 然后突然有想法了,想换个主题 具体操作 1.下载 grub 主题包 去这个地址下载主题(应该是这个地址): https://www.gnome-look.org/bro ...
- 基于QT的全自动超声波焊接机上位机追溯系统(已经在设备上应用)
应用说明: 本上位机程序是我在做锂电池产线项目的时候开发的,用于采集设备数据以及实现设备自动控制,下位机采用基恩士PLC,超声波机采用上海一家的超声波焊接机,实现电芯极耳的自动焊接,上位在设备焊接过程 ...