博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象第二次博客作业
阅读量:4693 次
发布时间:2019-06-09

本文共 2308 字,大约阅读时间需要 7 分钟。

       告别无穷无尽的求导,我们迎来了多线程电梯三连。这一单元的电梯作业主要考察多线程的协同和同步控制。在这三次作业中,我对多线程作业有了更深的理解,利用“生产者,消费者”的原理完成了三次作业。

(1)分析和总结三次作业

第一次作业:

       因为第一次作业不要求性能分,我采用了最无脑的写法:每读入一个请求,就开启一个电梯线程,将乘客运送到目的地,甚至连队列都没有使用。这种设计非常低效,无法捎带,也没有线程间的协作。

UML图:                时序图:

OO度量:

在move方法中模块设计复杂度和圈复杂度较高,这是由于我调度方法较为暴力,将接乘客与运乘客都放置在move方法里完成导致“高耦合”的现象发生。

第二次作业:

       我将请求队列放入电梯中,由电梯轮询,决定运送,捎带乘客的策略。由于只有一个电梯线程,只需要注意对请求队列操作的互斥即可。我把调度队列放在了电梯中,在本次作业还是可以接受的。但显然,这不是最好的架构。

 UML图:                    时序图:

OO度量:

第六次作业的复杂度控制的最好,只是在run方法中基本复杂度较高,这是由于我调度方法较为暴力,将接乘客与运乘客都塞在run方法里完成导致的。

第三次作业:

       第三次作业的一大难点就是乘客在不同电梯间的转乘。在这次作业中,我终于使用了调度器的思想,将请求队列放在调度器中。使用调度器,按照就近,空闲,可以直达的原则,将请求放入三个电梯的等待队列中,尽可能的明确每部分的功能:调度器只负责分配任务,而电梯只负责按照分配到的任务移动;至于乘客转乘,我将需要转乘的请求放入到达转乘楼层最近的电梯,由这个电梯将乘客运送至转乘楼层后,往请求队列中新加入一条新指令,再由调度器调度,最终运送至目的楼层。

 UML图:                  时序图:

OO度量:

第七次作业中,代码的复杂度控制的并不好,出现了大量基本复杂度过高的问题,我分析是因为在这些方法中,我使用了不少分支,循环语句,导致方法的非结构化程度过高。

 

(2)使用SOLID原则分析自己的程序结构

一、单一职责原则(SRP):每个类或方法都只有一个明确的职责

总体上,相比之前的作业,我在第三次电梯作业中算是比较好的完成了这一点,设置了大量职责明确的方法,但是在类层次上还有所欠缺,使得类显得比较臃肿。

二、开放封闭原则 (OCP):无需修改已有实现(close),而是通过扩展来增加新功能(open)

这一点我也比较好的完成,我第一次电梯作业的大部分方法可以一直沿用至三次作业。

三、Liskov's 替换原则(LSP):任何父类出现的地方都可以使用子类来代替,并不会导致使用相应类的程序出现错误。

四、接口分离原则(ISP):当一个类实现一个接口类的时候,必须要实现接口类中的所有接口,否则就是抽象类(abstract class),不能实例化出对象

五、依赖倒置原则(DIP):高层模块不应该依赖底层模块,两者都应该依赖其抽象。其实又是”面向接口编程,不要面向实现编程“的内在要求。

后三点,因为我没有使用接口,也没有类的继承,所以没有对它们的实现。

 

(3)分析自己程序的bug

       目前我被发现的bug均在转乘时发生,均是由于调度器线程不正常关闭,导致电梯没有完成任务就结束运行。具体原因是设置的条件不全,导致判断出错。导致电梯刚把乘客运送出楼层,还没关门,就因为判断电梯停止的方法违反了线程安全的原则错误访问了电梯内元素,提前停止了电梯。问题所在的类分别处于Elevator类中的出入方法和调度器类中的判断电梯停止运行的方法。

        我的bug都源于线程安全问题,主要是没有保证调度队列访问的互斥。导致电梯刚把乘客运送出楼层,还没关门,就因为判断电梯停止的方法违反了线程安全的原则错误访问了电梯内元素,提前停止了电梯。归结原因,还是在我的类和方法结构过于繁琐,导致某些条件重复判断或遗漏。

(4)分析自己发现别人程序bug所采用的策略

       在三次作业中,我都没有结合代码设计测试用例。总体来说,我只采用了大量数据“轰炸”的方法,在不同时间投放大量需要转乘的请求。本单元的测试与第一单元测试最大的不同是,bug复现性很差。同样的测试样例提交两次,会出现差异很大的结果,甚至会出现一次正确,一次错误的结果,另外,作为“强制在线”的评测,请求的投放时间也十分关键。个人感觉,使用对拍器制造大量数据对电梯的测试效果比较省心省力,效果也比较好。

(5) 心得体会

线程安全

       线程安全是这一单元作业的重中之重,在不会因格式扣分的情况下,绝大多数错误都来自于无法保证线程安全。刚开始接触多线程时,对多线程一知半解的我,(自以为)保证线程安全的做法就是无脑在方法上加synchronized关键字,这种做法在第三次作业受到了惩罚,不仅没有保证线程安全,还严重影响了电梯运行效率。在与同学的交流中,我对线程安全有了更深的理解,从盲目地锁方法变为了锁共享对象,渐渐对“锁”这一概念有了一些自己的理解。

设计原则

       “高内聚,低耦合”未必可以简化我们的电梯设计(因为只是想保证正确性的话,并不需要太复杂的结构),但一定可以大大地方便我们debug和修改,因为涉及线程间的协同和控制。添加新功能时,最好采用新加方法的方式实现,避免多次大量修改原有的代码。整个电梯的架构是牵一发而动全身的,为了保证线程间的协作(比如notify和wait的组合),常常要在许多不同的位置修改。

转载于:https://www.cnblogs.com/yezefeng12138/p/10760524.html

你可能感兴趣的文章
POJ 2378 Tree Cutting(树形DP,水)
查看>>
第二冲刺阶段个人博客5
查看>>
UVA 116 Unidirectional TSP (白书dp)
查看>>
第三方测速工具
查看>>
MySQL 网络访问连接
查看>>
在aws ec2上使用root用户登录
查看>>
数据访问 投票习题
查看>>
CIO知识储备
查看>>
cnblog!i'm coming!
查看>>
使用点符号代替溢出的文本
查看>>
Axios 中文说明
查看>>
fatal: remote origin already exists.
查看>>
gridview 自定义value值
查看>>
2018二月实现计划成果及其三月规划
查看>>
类名.class和getClass()区别
查看>>
12/17面试题
查看>>
LeetCode 242. Valid Anagram
查看>>
JSP表单提交乱码
查看>>
如何适应现代雇佣关系
查看>>
团队项目(第五周)
查看>>