2019北航面向对象课程第二单元作业(电梯)个人总结

一、从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略

  线程安全,是多线程编程的计算机程序的重要概念。在拥有共享数据的、多线程并行执行的程序中,只有保证线程安全、确保同步机制的正常运行,才能保证各线程正常运行而不出现各种运行异常或数据异常现象。

  多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,且不需要进行额外的同步或者在调用方进行其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。

  一个类要成为线程安全的,首先必须在单线程环境中有正确的行为。如果一个类实现正确,那么没有一种对这个类的对象的操作序列可以让对象处于无效状态,观察到对象处于无效状态、或者违反类的任何不可变量、前置条件或者后置条件的情况。其次,在被多个线程访问时,不管运行时环境执行这些线程有什么样的时序安排或者交错,它都必须仍然有如上所述的正确行为,并且在调用的代码中没有任何额外的同步。其效果就是,在所有线程看来,对于线程安全对象的操作是以固定的、全局一致的顺序发生的。

  我认为,好的设计架构,是保证线程安全和代码可复用性的基础。

  在第5次作业中,我主要设计了Requestinput、Dispatch、Elevator三个类,Requestinput负责输入指令,Dispatch负责接受并储存输入的指令、向电梯模块输出所要执行的指令、Elevator负责根据得到的指令进行运行。Requestinput、和Elevator是进程,共享共享对象Dispatch。线程安全主要体现在Requestinput输入指令到Dispatch和Elevator从Dispatch指令并运行互不干扰。

  在第6次作业中,在第5次作业的基础上,我在Dispatch中构造dowith()函数,使得Elevator在模拟电梯运行时,可以实时讨论是否进行捎带,在符合要求的情况下尽可能进行捎带,减少相同指令集对应的程序运行时间;相应的,Elevator中构造queue动态队列存储电梯“一次”运行中所要执行的指令。这次作业的线程安全,还体现在判断捎带函数对Dispatch中指令队列的调用与改变上。

  在第7次作业中,Dispatch中maina、mainb、mainc分别对应应该改由Elevatora、Elevatorb、Elevatorc执行的指令,而Elevatora、Elevatorb、Elevatorc中又分别有queuea、queueb、queuec存储电梯“一次”运行中所要执行的指令。Requestinput输入的指令,如果可由某电梯直达,则直接放入对应的main队列中,否则先进行拆分,然后循环判断能否直达、是否需要拆分,直到所有拆分出来的指令都放入了对应的main队列中。此次电梯的线程安全设计在前两次作业的基础上,还主要体现在,Elevatora、Elevatorb、Elevatorc三个进程的运行互不影响,对maina、mainb、mainc的输入与输出通过加“锁”保证安全。

 

二、基于度量来分析自己的程序结构

(1)度量类的属性个数、方法个数、给个方法规模、每个方法的控制分支数目、类总代码规模

第5次作业:

第6次作业:

第7次作业:

(2)计算经典的OO度量

第5次作业:

第6次作业:

第7次作业:

(3)画出自己作业的类图,并自我点评优点和缺点,要结合类图做分析

第5次作业:

第6次作业:

第7次作业:

(4)通过UML的协作图(sequence diagram)来展示线程之间的协作关系

第5次作业:

第6次作业:

第7次作业:

(5)从设计原则检查度量,检查自己的设计,并按照SOLID列出所存在的问题

 

第5次作业

第6次作业

第7次作业

SRP单一责任原则

无问题

无问题

电梯类Elevatora、Elevatorb、Elevatorc不仅负责实现对电梯运行的模拟,还负责事实判断是否进行捎带,以及存储当前正在执行或即将被执行的一组运动指令

OCP开放封闭原则

无问题

无问题

不同名称、不同载客量、不同运行速度的电梯Elevatora、Elevatorb、Elevatorc的不同信息直接写入电梯类中,而不是通过参数传入,代码重用性降低,不利于对代码进行拓展

LSP里氏替换原则

无问题

无问题

无问题

DIP依赖倒置原则

无问题

无问题

高层模块(例如:电梯模块、调度器模块)依赖于底层模块(Polyrequest)

ISP接口分离原则

无问题

无问题

无问题

 


三、分析自己程序的bug

(1)分析自己未通过的公测用例和被互测发现的bug;特征、问题所在的类和方法

(2)特别注意分析哪些问题与线程安全相关

(3)关联分析bug位置与设计结构之间的相关性

在第6次作业中,在Dispatch调度器类中对是否捎带进行判断讨论时,我对捎带条件的讨论出现了重复之处:

 

这些错误导致了面对这样的数据集
[0.0]0-FROM--2-TO—3
[0.0]8-FROM-14-TO—3
的时候,会在到达-3层后持续下降,无法停止,更无法返回上层执行接下来的指令。重新讨论捎带条件,可以对错误语句进行修正:

可以成功改正之前出现的错误。

四、分析自己发现别人程序bug所采用的策略

(1)列出自己所采取的测试策略及有效性,并特别指出是否结合被测程序的代码设计结构来设计测试用例

(2)分析自己采用了什么策略来发现线程安全相关的问题

(3)分析本单元的测试策略与第一单元测试策略的差异之处

  在第5次作业中,我主要测试他人代码基本的输入指令、存储指令和取出指令并进行运行等功能。因为此次作业仅有一台,且不要求捎带,故没有什么错误的空间。

  在第6次作业中,我除了进行在第5次作业中进行的测试内容外,还考察了他人代码捎带功能的强弱程度。为了测试捎带功能,我构造了许多组十分考验捎带的指令集,测试表明最快运行时间为27s左右,而组里很多份代码需要60s至70s才能运行完毕,最慢的一份代码需要84s——但提交互测数据的结果显示,大家都处于测试机认定的合理时间范围之内♪(・ω・)ノ。

  在第7次作业中,在进行前两次作业已经进行了的测试的基础上,我就需要转乘的情况进行了测试。事实证明,还是有代码对于换乘情况考虑不清,讨论不全,甚至无法执行拆分后的第二条指令(比如指令1-FROM-7-TO—3,再被拆分成1-FROM-7-TO-1和1-FROM-1-TO—3后,第二条指令1-FROM-1-TO—3无法被执行)。

 

五、心得体会

从线程安全和设计原则两个方面来梳理自己在本单元三次作业中获得的心得体会

  线程安全,是多线程编程的计算机程序的重要概念。在拥有共享数据的、多线程并行执行的程序中,只有保证线程安全、确保同步机制的正常运行,才能保证各线程正常运行而不出现各种运行异常或数据异常现象——而好的设计架构,是保证线程安全和代码可复用性的基础的基础的基础(重要的事情说三遍♪(・ω・)ノ)。在进行第6次作业和第7次作业时,我都因为不完善的设计出现了线程矛盾、死锁等方面的问题,最后不得不推倒重来(orz)。希望各位看官和我本人都能吸取这些血泪教训,构架千万种,线程第一种,设计不完善,程序媛两行泪♪(・ω・)ノ

 

 

 

posted @ 2019-04-19 21:55  这里是罗白沁呀  阅读(251)  评论(0编辑  收藏  举报