OO第二单元总结——电梯

第一次做业——FAFS调度算法

1.设计策略设计模式

第一次做业是单部电梯的傻瓜调度,因此电梯的运做不是难点。对于初次接触多线程的我来讲,多线程之间的协同和同步控制是此次做业的难点。做业的总体思路我采用的是典型的生产者-消费者模式,请求输入是一个生产者线程,调度器至关于一个仓库,电梯则是消费者线程。安全

我采用的是共享对象来实现的多线程间的同步控制,输入请求线程中有一个判断输入是否结束的共享变量,调度器中有一个当前队列是否为空的共享变量。关于多线程的协同,我采用的是轮询的方法来控制电梯线程。第一次并不太会使用wait和notify等,致使采用暴力轮询的方法CPU占用率偏高。
多线程

 

2.基于度量分析程序结构框架

类图函数

这四个类的功能较为独立且简单。RequestInput 是输入线程,Dispatcher 是调度器,ElevatorRun是电梯线程。输入线程和电梯线程分别组合同一个调度器来实现线程间的交互。性能

傻瓜电梯的Complexity Metrcis

分析结果中能够看到ev, iv, v这几栏,分别代指基本复杂度(Essential Complexity (ev(G))、模块设计复杂度(耦合度)(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈复杂度(独立路径的条数)。OCavgWMC两个项目,分别表明类的方法的平均循环复杂度和总循环复杂度。学习

 

  

SOLID设计检查 

  • 单一职责原则(SRP):符合,每个类和方法功能单一。测试

  • 开放封闭原则(OCP):输入请求类是符合这一原则的,但电梯类和调度器类是不符合该原则的。第一做业的调度算法比较简单,对于以后优化的调度可扩展性不高。优化

  • 里氏替换原则(LSP):因为没有使用继承,未能体现

  • 接口隔离原则(ISP):因为没有使用接口,未能体现

  • 依赖倒置原则(DIP):不符合,电梯类和输入请求类都依赖于调度器类,调用了其提供的一些方法,所以若是调度器类对外接口发生改动,则其余两类也须要改动。

 

3.BUG分析

在写此次做业的过程当中,如何控制线程的结束真的难到了我。屡次尝试,有彻底没输出的时候,有程序没法结束的时候。最后在我debug半天以后(不过用的是轮询方法)总算解决了这个问题。本次做业真的很简单,实现以后测试是没有bug的。强测第一次得满分……

 

第二次做业——单部多线程可捎带调度(ALS)电梯

1.设计策略

第二次做业在第一次做业的基础上,大致框架是没有改变的,依然是生产者-消费者模型。但此次调度算法是ALS算法,线程间的协同与同步控制我抛弃了以前轮询的作法,采用了wait和notify等。

个人调度器内的队列一直用的是LinkedBlockingQueue,它是个阻塞的线程安全的队列,底层采用链表实现。

我采用的入队方法是put。put方法 :若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素

出队方法采用的是take。take方法看起来就是put方法的逆向操做。若队列为空,发生阻塞,等待有元素;队列不为空,从队首获取并移除一个元素

线程间的协同与同步控制依然是共享对象的方法。不过当队列为空时再也不是轮询方法,而是wait,每当put操做就唤醒沉睡的线程,若从队列中读到NULL(LookAtFirst函数在队列为空时,若输入未结束则wait,不然获得NULL)则电梯进程结束。

 

2.基于度量分析程序结构

类图

相比于第一次做业,此次做业各个类的方法以及属性较多。此次我添加一个Button类,其实仿照现实生活中的电梯按钮。电梯线程有两个Button类,一个外部按钮,以楼层为索引统计各个请求;一个内部电梯,以楼层为索引统计电梯内的请求要到的目的地。关于该楼层的请求可否捎带等方法实现都是在Button类内实现的。由于增长了Button类,Button的信息也须要同步,故而额外增长了不少方法来实现其同步。

这样有好处也有弊端。有的人实现捎带,是在每一个楼层遍历调度器类的队列,这样只需维护一个队列信息的同步,但这样每次遍历队列所有请求,也是一种浪费。我增长Button类可使得操做变得更加直观,实际上调度器类的队列是按加入时间记录的,而Button类是按楼层来记录的。

 

ALS Complexity Metrcis

 ElevatorRun类较为复杂,由于此次的调度算法再也不那么简单,增长了不少方法来实现捎带。

ALS Dependency Metrcis

依赖度分析度量了类之间的依赖程度。有以下几种项目:

  1. Cyclic:指和类直接或间接相互依赖的类的数量。这样的相互依赖可能致使代码难以理解和测试。

  2. Dcy和Dcy*:计算了该类直接依赖的类的数量,带*表示包括了间接依赖的类。

  3. Dpt和Dpt*:计算了直接依赖该类的类的数量,带*表示包括了间接依赖的类。

 

 

SOLID设计检查

SRP:较符合,三个主要的类分别负责请求的获取输入,对请求的调度分配,电梯运行。

OCP:较符合。为了可以实现多部电梯的ALS调度,我给每部电梯扩展了外部按钮以及内部按钮的功能,使得每一个电梯的运行变得独立。这样的框架使得我在第三次的做业只需改动调度器。

LSP:没有使用继承,未能体现

ISP:没有使用接口,未能体现

DIP:不符合,由于个人类与类之间存在组合关系仍然出现了高层模块依赖底层模块的现象。

 

3 .BUG分析

在本身运行了部分数据后,个人程序并无出错。固然在逻辑上我认为也是没错的。不过多线程的BUG是手动测试测不出来的,对于没有评测机的我来讲不管是测本身的仍是别人的潜在Bug都比较困难。

 

4.电梯调度算法分析

其实此次做业个人性能分几乎为0。我采用的捎带方式便是指导书中所述的最原始的主请求捎带。个人调度在去接主请求的路上是不能捎带的。哎……都怪本身懒,性能分奇低。

我认为比较优化且符合实际状况的,即既能够尽可能缩短总运行时间又能够照顾每一个请求的用户体验的算法是SCAN算法。电梯除了静止的状态,老是上行以后下行,下行以后上行,即在一趟来回中解决尽量多的请求。按照楼层顺序依次服务请求,让电梯在最底层和最顶层之间连续往返运行,在运行过程当中响应处在于电梯运行方向相同的各楼层上的请求。

由此看来,我以前的捎带算法是靠主请求来决定电梯运行的方向的,而scan算法是靠运行过程当中请求分布楼层状况来决定运行方向的。其实在我实现了Button类以后,scan算法是很好实现的。啊啊啊……,后悔当初没有勤快一点!!

 

第三次做业——多电梯

1.设计策略

第三次做业要求模拟多部智能电梯,而且存在转乘的状况。单独电梯我仍是采用的ALS捎带调度算法。此次改动较大的是调度器类。

此次采用了两层调度的策略。对于须要转乘的请求,我在调度器内将其拆分为两个请求。而后让第一个请求分配进优先级较高的电梯。当某个请求从电梯内出来,我会判断该ID是否须要转乘,若须要转乘,则对其第二个请求分配入当前优先级最高的电梯。一个ID的拆分指令之间的协同,我是经过调度器类的一个Button类来实现的。其实际为一个以ID为Key的hashMap,只有当前ID的第一个请求完成时,才能将第二个请求分配入相应的电梯队列(此次调度器类有三个电梯的队列。)

电梯运行结束的控制条件为输入结束且调度器类中的hashMap为空。这样我就能保证完成所有任务,不会提早结束了。

 

2.基于度量分析的程序结构

类图

 

此次做业在第二做业的基础上只是调度器类作了较大改动,大致框架未变。

SS Multielevator Complexity Metrcis

 由上图可见,指令拆分的中间楼层的计算较为复杂,以及对于当前请求优先电梯的计算也较为复杂。其实只是判断条件比较多而已,并未以为多复杂啊……

SS Multielevator Dependency  Metrcis

 

由上图可见,个人类之间的依赖关系是比较多的。我采用的设计模式是观察者模式,订阅者(多部电梯)会依赖观察者,观察者须要通知订阅者因此也要依赖它们。对于某些大佬的上图中Cyclic一列为0,不知道是怎么办到的。既然要实现多各种之间的信息交互,是怎么减小类之间的依赖关系的呢?望赐教!

 

SOLID 分析

SRP:逻辑上认为这几个类的功能是比较单一的。不过由上面度量结果图能够看出,调度器的代码规模大且控制分支多。

OCP:符合,若是再增长电梯的数目,只需对调度器类增长几个电梯的队列便可,相应方法的改动也不多。

LSP:未使用继承,没法体现

ISP:未使用接口,没法体现

DIP:不符合。

 

3.BUG分析

感受此次线程单元的BUG仍是主要出如今如何控制线程结束以及保证线程安全上。

 强测中我制造了一个40条指令的输入,只hack到了一我的。能力有限,我也想要强大的评测机……

 

心得体会

 其实我以为我在多线程安全方面仍是能够优化的。为了保险起见,我给不少方法都加了锁,其实这其中必定是有多余的状况。多个线程或方法之间的同步与互斥是须要本身考虑来化简的。

我感受一个单元的时间对于咱们彻底掌握多线程的知识点是彻底不够的。其实只要你胆子大,不多的线程知识是彻底能够搞定这些做业的。就算你使用了多线程的知识,这三次的做业咱们也只是对个别知识点使用的比较多。由于了解的不够多,知识掌握的不够全面,咱们的实现方法变得很单一。一直有种只知其一;不知其二的感受。固然"师傅领进门,修行看我的”,这些知识体系的完备仍是须要咱们花大量的额外时间来学习的。

加油啦,本身千万不要浅尝辄止啊,不要作一只井底之蛙共勉

相关文章
相关标签/搜索