OO第二单元--多线程电梯

1、设计策略

(1)单电梯:

  a、线程分工:

    elevator、request两个线程。设计模式

      elevator线程主要负责乘客的接送和进出。安全

      request线程是接收乘客信息。多线程

    control是缓冲器,用来保存elevator和request两个线程共享的乘客队列。架构

  b、调度策略:

    以电梯当前楼层和运行状态为基准,若是电梯是上行的,而且高于当前楼层还有乘客要进出就上行,不然判断是否低于该楼层有需求,若是有就下行。反之亦然,如果没有需求,则令电梯中止。对于乘客的调度则是到了规定楼层,能出则出,能进则进。函数

(2)多电梯1.0:

  a、线程分工:

    elevator类的五个电梯线程以及request线程。学习

    elevator线程主要负责乘客的接送和进出。测试

    request线程是接收乘客信息。spa

    control是缓冲器,用来保存elevator和request两个线程共享的乘客队列。线程

 

  b、调度策略:

    基于第一次做业的单电梯,将request中得到的乘客,平分到每一个电梯中。设计

(3)多电梯2.0:

  a、线程分工:

    elevator类的若干个线程以及request线程。

    elevator线程主要负责乘客的接送和进出。

    request线程是接收乘客信息。

    control是缓冲器,用来保存elevator和request两个线程共享的乘客队列,以及保存电梯类的个数。

  b、调度策略:

    扩展PersonRequest类的功能,便于进行换乘操做。根据ABC不一样的电梯停靠楼层对接收的乘客进行分类。可以直达的尽可能直达,如果出现都能直达的状况根据ABC的优先级进行分类。如果不能直达的,则根据出发楼层ABC进行分类,换乘楼层集中在固定楼层一、五、15,便于进行操做,减小开关门的时间损失。对于同类别的不一样电梯的乘客调度同第二次做业,对于电梯的运行同第一次做业。

2、第三次做业的可扩展性(SOLID原则)

(1)SRP(单一职责)原则

   request类主要进行生产者线程,elevator进行电梯的主要功能,control进行乘客信息的调度以及保存。三类的功能都不相同,符合单一职责的原则。在control中虽然有不少的方法,可是执行的目的都是十分简单,仍是符单一职责原则。

(2)OCP(开放封闭)原则

   由于没有在写做业时,没有考虑代码的可扩展性,不少方法在第三次多电梯的实现中,进行了些许的调整,若是该电梯还要进行一些扩展操做,我想对于这些方法仍是应该要进行调整。所以我以为第三次做业的OCP原则仍是不是很好。

(3)LSP(替换)原则

   第三次做业中我单独写了三个电梯类,没有归类到一个父类里面,由于在建立类,以及执行过程当中都是用的电梯序号,因此没有这方面的问题。

(4)ISP(接口隔离)原则

    对于不一样电梯,经过电梯索引来对电梯进行操做,在后续的几回拓展都获得一个很好的实现,因此相对来讲接口隔离实现得比较好。可是对于电梯没有经过属性规范,而是独立的创建了三个电梯类,我以为这一方面的接口原则就处理得不是很好。

(5)DIP(依赖倒置)原则

   control缓冲区元素的创建依赖request的运行,elevator的执行和创建依赖control,没有出现循环依赖的状况,仍是很好的知足了依赖倒置的状况。

3、度量分析

 

(1)第一次做业:

    UML

 

 

 

    复杂度分析

 

    a、dependency

 

 

 

 

    b、 complexity

 

    总结

 

     复杂度较好,可是对于control的setUpFloor方法的复杂度就比较高,这跟个人调度策略有着很大的关系,四次用到循环,结果做为条件的一种嵌套,都增长了复杂度,而这些在后续几回做业都有体现。

 

(2)第二次做业:

    UML

    复杂度分析

    a、dependency

    b、 complexity

 

 

    总结

     这一次做业的的独立性相对比较好,可是复杂度分析有不少的方法爆红,特别是setUpFloor的方法,我想应该是在该方法有四个循环,致使该方法的复杂度很高,并且得出的结果又会用来下一次的判断条件,因此有一个嵌套的复杂度,可是关于该方法的修正没有比较好的想法。

(3)第三次做业:

    UML

 

 

 

    复杂度分析

    a、dependency

 

 

 

    b、 complexity

    总结

     此次做业的依赖性除了MainClass由于须要其余类来辅助执行,因此相对来讲大一点其余还好。复杂度分析图中,相比于第二次做业,爆红的方法又加了一个addRequest方法,由于此次做业的调度设计涉及指定楼层,在没有找到一个统一的方法的时候,只能经过打表的方式进行调度,我以为或许能够经过将该函数进一步细化,获得一个复杂度较好的函数。

(4)plantMUL

 

 

 

4、bug分析

(1)自我bug分析

    互测测到的bug主要是错误使用了notify,随机的唤醒线程使得我一些线程长睡不醒,改为notifyAll后就不会出现这样的随机性了。

   值得一提的是第三次做业的中测,因为对于notifyAll、wait的理解不够深刻,致使我在关于wait对象一判断就唤醒,出现了一些线程wait条件判断被阻塞,致使测试RE差点死于中测。可是通过这一次我好好学习了notifyAll的使用,发现只有在wait对象状态发生改变的时候,即true变成false,才可以notifyAll

(2)hack的bug

    第一次做业hack到的是暴力轮询的bug;第二次做业没有hack到;第三次做业hack到的是RE的bug,我以为应该就是我中测碰到的那个类型的bug。

5、bug策略

   此次hack构造,主要从很长时间再来一我的hack暴力轮询,经过一次来不少人hack调度分配线程冲突。可是碰到一些评测到没法复现的bug仍是感到多线程就是运气的问题,可是若是一个安全的程序不该该依赖于运气,应该要有一个充分的维护。与第一单元相比,这一次的做业在调试,bug复现的难度上大大的提升,并且有时候原理搞不明白,也很难找到bug。因此我认为仍是应该要细细的分析程序,经过自动测试的方式只能是一种手段,还应该从从线程的程度上考虑,避免阻塞的状况发生。

6、心得体会

   在这一次做业中,从线程安全上考虑应该要理清楚线程的执行顺序,线程共享的对象。设计原则上应该尽量的符合开闭原则,减小一些重复操做和闭合操做,防止死锁的产生。多线程的体验中,我学习到了一些设计模式,虽然理解还不是很透,可是对于多线程的协做感到十分的神奇,并且感受十分的接近现实生活。并且感受学习写程序,不该该依赖于专有的设计架构,应该多想一想多尝试一些原理。否则再后续调bug,可能本身就算是小黄鸭讲解程序,也仍是不会找到程序的bug。同时这种多线程的使用,在过程式代码中是至关难实现得,又进一步了解了面向对象程序!

相关文章
相关标签/搜索