欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-06-19 16:01:55
一、设计策略 (1)单电梯: a、线程分工: elevator、request两个线程。 elevator线程主要负责乘客的接送和进出。 request线程是接收乘客信息。 control是缓冲器,用来保存elevator和request两个线程共享的乘客队列。 b、调度策略: 以电梯当前楼层和运行 ......

一、设计策略

(1)单电梯:

  a、线程分工:

    elevator、request两个线程。

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

      request线程是接收乘客信息。

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

  b、调度策略:

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

(2)多电梯1.0:

  a、线程分工:

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

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

    request线程是接收乘客信息。

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

 

  b、调度策略:

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

(3)多电梯2.0:

  a、线程分工:

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

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

    request线程是接收乘客信息。

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

  b、调度策略:

    扩展personrequest类的功能,便于进行换乘操作。根据abc不同的电梯停靠楼层对接收的乘客进行分类。能够直达的尽量直达,若是出现都能直达的情况根据abc的优先级进行分类。若是不能直达的,则根据出发楼层abc进行分类,换乘楼层集中在固定楼层1、5、15,便于进行操作,减少开关门的时间损失。对于同类别的不同电梯的乘客调度同第二次作业,对于电梯的运行同第一次作业。

二、第三次作业的可扩展性(solid原则)

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

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

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

   因为没有在写作业时,没有考虑代码的可扩展性,很多方法在第三次多电梯的实现中,进行了些许的调整,如果该电梯还要进行一些扩展操作,我想对于这些方法还是应该要进行调整。因此我觉得第三次作业的ocp原则还是不是很好。

(3)lsp(替换)原则

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

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

    对于不同电梯,通过电梯索引来对电梯进行操作,在后续的几次拓展都得到一个很好的实现,所以相对来说接口隔离实现得比较好。但是对于电梯没有通过属性规范,而是独立的建立了三个电梯类,我觉得这一方面的接口原则就处理得不是很好。

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

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

三、度量分析

 

(1)第一次作业:

    uml

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

 

 

 

    复杂度分析

 

    a、dependency

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

 

 

 

 

    b、 complexity

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

 

    总结

 

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

 

(2)第二次作业:

    uml

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

    复杂度分析

    a、dependency

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

    b、 complexity

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

 

 

    总结

     这一次作业的的独立性相对比较好,但是复杂度分析有很多的方法爆红,特别是setupfloor的方法,我想应该是在该方法有四个循环,导致该方法的复杂度很高,而且得出的结果又会用来下一次的判断条件,所以有一个嵌套的复杂度,但是关于该方法的修正没有比较好的想法。

(3)第三次作业:

    uml

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

 

 

 

    复杂度分析

    a、dependency

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

 

 

 

    b、 complexity

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

    总结

     这次作业的依赖性除了mainclass因为需要其他类来辅助执行,所以相对来说大一点其他还好。复杂度分析图中,相比于第二次作业,爆红的方法又加了一个addrequest方法,因为这次作业的调度设计涉及指定楼层,在没有找到一个统一的方法的时候,只能通过打表的方式进行调度,我觉得或许可以通过将该函数进一步细化,得到一个复杂度较好的函数。

(4)plantmul

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

 

 

 

四、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。

五、bug策略

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

六、心得体会

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