第一次作业

设计思路与感想

第一次作业是要求有捎带的电梯实现, 第一次作业是花费的时间比较长的一次,花费了很多的时间去思考架构的问题.起初是想要搞三个线程的:输入线程,调度器线程和电梯线程,想要搞一个连锁的生产消费模型,但是在调度器线程和电梯线程在交互的时候出现了一些问题.

  1. 对run方法操作最小化的思考,

    • 对于输入线程和调度器线程来说就是比较简单的,对于电梯线程我考虑了要不要添加一些非最小化的操作,比如:电梯加入moveTo()方法.
    • 这样的方法在while(true)里面是不合适的,完全可以通过每循环一次移动一楼
    • 这个moveTo具有占用大量时间的问题,因为上楼就要有0.4s的消耗,上楼这段时间没有办法执行下一次循环来响应请求.
    • 所以run方法中含有while(true)建议每次循环都做最少的事,由小组成一个大的
  2. 对于三个线程即:输入,调度器,电梯线程的思考
    • 这块我起初是想实现三个线程但是操作上还是出现了问题,虽然构建了流水线来搞,但是电梯线程有一个上下楼的等待时间,这个对于调度起来说,给不给电梯捎带请求是很难的一点,这个时候就需要加入一个电梯的返回来实现,而我没有这么做.
    • 我是直接将电梯线程join到了调度器线程里面,这个时候电梯内部没有了while(true), 等到电梯执行完了调度器再继续执行.
    • 交了作业以后,我发现其实此时的电梯线程已经没有必要再做成一个线程了,它完全就是一个普通的对象了.于是在下一次作业,将三线程变成了两线程
  3. 本次作业采用了als算法,性能不是很好,还是用look性能好一些.

类图分析

  • 类之间调用的复杂度比较高,还是有一定的改进空间

度量分析

Method ev(G) iv(G) v(G)
"Command.Command(boolean)" 1 1 1
"Command.addCommand(int)" 1 3 3
"Command.getCommand()" 1 3 3
"Dispatcher.Dispatcher(LinkedList,Elevator,Command,boolean)" 1 1 1
"Dispatcher.checkIfSomeBodyGetIn()" 3 2 3
"Dispatcher.checkIfSomeBodyGetOff()" 3 2 3
"Dispatcher.closeDoor()" 1 2 2
"Dispatcher.downFloor()" 1 2 2
"Dispatcher.getIn()" 3 4 4
"Dispatcher.getOff()" 3 3 3
"Dispatcher.isSameDir(PersonRequest)" 3 4 5
"Dispatcher.openDoor()" 1 2 2
"Dispatcher.run()" $\color{red}{6}$ $\color{red}{13}$ $\color{red}{15}$
"Dispatcher.setStop(boolean)" 1 1 1
"Dispatcher.upFloor()" 1 2 2
"Elevator.Elevator(LinkedList,Command,Integer,boolean)" 1 1 1
"Elevator.arrive()" 1 1 1
"Elevator.close()" 1 1 1
"Elevator.down()" 1 2 2
"Elevator.getFloorNumNow()" 1 1 1
"Elevator.getIrq()" 1 1 1
"Elevator.isRuning()" 1 1 1
"Elevator.open()" 1 2 2
"Elevator.run()" 1 5 5
"Elevator.setRuning(boolean)" 1 1 1
"Elevator.up()" 1 2 2

有一个方法的复杂度比较高,其他的方法还好.这个run方法里面多次调用了elevator里面的方法,而且多次启动新线程,可能是导致复杂度上升的原因.

时序图

第二次作业

设计思路与感想

本次作业是多部电梯之间协同工作,且设计了容量问题,我是将上次的作业进行了优化,将上次作业中的调度器和电梯线程之间合并为了一个电梯线程,这样的话,多部电梯,就只用一个电梯类来刻画即可以达到目的,同时电梯内部的调度策略换为了LOOK,电梯间的调度策略是为每部电梯定义了一个函数:f(a,b,c,d,e,f);

  • a表示电梯所在的楼层
  • b表示电梯的运行状态上还是下
  • c表示该请求所在的楼层
  • d表示该请求要去往的楼层
  • e表示电梯外已有的等待人数
  • f表示电梯内已有的人数
  • 函数返回一个值来衡量电梯的负载情况

主线程读到请求后,直接分配给f(a,b,c,d,e,f)值最小的电梯来运行.由于与上次的改动并不多,也就不会出现线程安全的问题,而且这样的调度策略在性能上也是比较好的一个动态调度方案.

类图



类图也比较简单,只有两个类,elevator类结合了上次作业的捎带功能,main方法加入了一个电梯之间的分发问题.

度量分析


本次作业中最大值是getfd()方法,这个方法就是上文中提到的为了调度所定义的f(a,b,c,d,e,f) ,可能在实现上还是有面向过程的思想,导致该方法循环复杂度极高.

时序图

第三次作业

设计思路与感想

  • 本次作业是多部多类型电梯之间的调度.
  • elevator基本没有更改,只是增加了一些配置内容,这里是直接使用了type和if判断,这与面向对象的设计思想有不符的地方,但是为了各种安全性问题,还是决定不进行大改了
  • 因为上一次的类数过少,有些类它的内部可能干的事情太多了,于是又抽象出了两个调度器类,不过这次它不再是一个线程了,而只是一个管理者.同类型电梯之间的调度方案和第二次作业相同,抽象出了Dispacher类.不同类之间采用先拆分为直达请求的方法,然后为电梯分配,于是又有了个DispacherTop类.从上到下进行管理
  • 这次被hack出了线程安全问题,但是最后还是没有找到问题在哪,因为我是尽量减少共享对象的设计方案,所以可能是在增加电梯时的管理层级出现了问题.

类图



  • 可以看到出现了跨层之间的调度,这个是因为请求拆分以后进入一个队列需要为电梯调用,那么拆分后的两条请求,第一条执行完毕需要告诉顶层的调度器去继续执行.

度量分析



  • 类的复杂度比较高,原因在于我没有把请求队列,等待队列这些部分抽象出来,来降低耦合度.其实可以抽象出等待队列,来避免跨层之间的调度,而是都与等待队列来交互,实现解耦.

时序图

SOLID设计原则分析

  1. Single Responsibility Principle:单一职责原则:一个类应该只有一个发生变化的原因
  • 本次作业尽量做到单一职责原则,但是有些地方因为拆分为类比较复杂,于是选择了耦合.
  1. Open Closed Principle:开闭原则:一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭

    • 在每次作业中都有重新设计类图的结构,所以类都是改变过的,显然没有遵循到开闭原则.
  2. Liskov Substitution Principle:里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象
    • 没有使用继承,在第三次作业中使用了type,所以也没有遵循这个规定.
  3. Law of Demeter:迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
    • 没有遵循到这个设计原则,也正因为没有使用第三方来发送信息,所以导致耦合度较高
  4. Interface Segregation Principle:接口隔离原则:

    1.客户端不应该依赖它不需要的接口。

    2.类间的依赖关系应该建立在最小的接口上。

    • 未使用接口,同继承,增加了耦合度.
  5. Dependence Inversion Principle:依赖倒置原则:

    1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。

    2、抽象不应该依赖于细节,细节应该依赖于抽象。

    • 第三次作业中,上层模块依赖了底层模块,违反了依赖倒置原则.且没有实现抽象增加了耦合度

BUAAOO第二单元代码分析的更多相关文章

  1. BUAAOO第一单元代码分析

    1.HomeWork1 思路 一个主类用于字符串得操作, 一个Poly类用于对一个多项式进行抽象,用Arraylist来对term进行封装.内部含有求导方法,添加并合并同类项的方法,toString方 ...

  2. BUAAOO第二单元多线程电梯作业总结

    第二单元多线程作业需要保证线程安全

  3. OO第二单元作业分析

    前言 这一单元关于线程安全的作业结束了,在助教提供的接口的帮助以及老师提供的设计模型的指导下,这三次作业还是相对轻松地完成了,中间也没有出现什么bug,可能就是因为简单的逻辑不容易出错吧,可惜两次都由 ...

  4. BUAA-OO第二单元小结

    一.设计策略 三次作业中,由于前两次作业都只有一部电梯,因此我的线程只有两个,一个等待队列输入进程,以及一个电梯运行进程.等待队列输入进程实现十分简单,只需要根据输入把request添加到等待队列即可 ...

  5. BUAAOO第二单元总结之电梯问题

    ---恢复内容开始--- Homework1 傻瓜电梯 程序架构 第一次题目非常简单,思考也非常简单,一部电梯傻瓜调度.将命令入公共的队列,电梯从公共队列中取命令即可,其中只需要使用ArrayBloc ...

  6. 【BUAA-OO】第二单元作业总结

    第二单元作业总结 ——电梯恐惧症患者的极限自救 一.   第一次作业程序分析 1.     设计策略简略分析 线程:主线程.输入线程和电梯线程,另有一个持有请求队列的调度器,一个对输入进行处理的Req ...

  7. OO第二单元作业小结

    前言 转眼已是第九周,第二单元的电梯系列作业已经结束,终于体验了一番多线程电梯之旅. 第一次作业是单电梯的傻瓜调度,虽然是第一次写多线程,但在课程PPT的指引下,写起来还是非常容易:第二次作业是单电梯 ...

  8. OO第二单元总结

    这一单元作业是围绕电梯调度进行展开,并引进了多线程的概念.与第一次作业比较类似,作业难度也是逐渐推进,从最开始的单部电梯先来先服务(傻瓜式调度),到之后的单部电梯可稍带调度,到最后的多部电梯分楼层调度 ...

  9. OO_第二单元总结

    第二次总结博客(电梯单元) 16071070 陈泽寅 2019.4.20 一:多线程实验初感 这个单元是多线程设计的实践单元,主要让我们运用多线程的原理与思想去完成一个模拟电梯运行的策略.从最开始的单 ...

随机推荐

  1. Captain technology INC:高性能电池助力新能源车企销量暴涨

    来自七个欧洲国家的11个合作伙伴共聚一堂,投身于HyFlow研究项目,共同开发一种可兼顾高性能和能源需求的混合氧化还原液流储能系统.为此,科学家们希望将高性能钒氧化还原液流电池与超级电容器相结合. 到 ...

  2. NGK算力持有好处多多!SPC、VAST等免费拿!

    众所周知,NGK是分布式存储的,作为Web3.0以及数字经济时代的基础设施,为数字加密市场带来了全新的商业模式和经济业态,但是,这只是一个重要的起点,真正的价值还在后面! 为了满足NGK生态建设者强烈 ...

  3. C++算法代码——细胞问题

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1152 http://ybt.ssoier.cn:8088/problem_show. ...

  4. java的read方法

    public class RandomAccessDemo6 { public static void main(String[] args) throws IOException { RandomA ...

  5. Spark + GraphX + Pregel

    Spark+GraphX图 Q:什么是图?图的应用场景 A:图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种网状数据结构,表示为二元组:Gragh=(V,E),V\E分别是顶点 ...

  6. vue中v-model的学习

    v-model在表单元素input.radio.checkBox.textarea创建双向数据绑定,他会根据类型选取正确的方法来更新元素,本质不过是语法糖,负责监听用户的输入操作以更新数据并对一些极端 ...

  7. 弹性盒布局详解(display: flex;)

    弹性盒布局详解 弹性盒介绍 弹性盒的CSS属性 开启弹性盒 弹性容器的CSS属性 flex-direction设置弹性元素在弹性容器中的排列方向 主轴与侧轴(副轴) flex-wrap设置弹性容器空间 ...

  8. AOP +FreeSql 跨方法异步事务

    AOP +FreeSql 跨方法异步事务 Autofac.Extensions.DependencyInjection Autofac.Extras.DynamicProxy Castle.Core. ...

  9. mysql 单表下的字段操作

    如下只介绍单表的添加.更新.删除.查询表结构操作,查询数据操作范围太大用单独的篇幅来讲解: 查看表结构 desc test_tb; Insert 插入数据 插入 = 添加 为表中指定的字段插入数据 C ...

  10. 微信小程序进入广告实现

    <view class="container"> <image src="../../imgs/swiper1.jpg"></im ...