OO 第二单元总结

OO 第二单元总结

一、作业架构设计与分析

1、homework5

1.1 UML 类图

1.2 UML 协作图

1.3 架构设计

请求处理方式

在此次作业中我采用了生产者消费者模式,InputThread 线程获取输入请求,再通过 NewMainBuilding 线程分发给各个楼座(SubBuilding),电梯作为消费者从各个楼座获取请求并进行处理。

电梯调度策略

我在本次作业中没有设计调度器,而是采用 look 算法,让电梯上下来回移动,在有请求的楼层开关门,若当前方向上没有请求,则改变运行方向。

1.4 同步块的设置和锁的选择

在本次作业中我使用 synchronized 将自定义的共享队列类(MyQueue) 以及 SubBuilding 的所有方法都锁了起来。

2、homework6

2.1 UML 类图

2.2 UML 协作图

2.3 架构设计

请求处理方式

在上一次作业中,我将新主楼作为一个线程用以分发请求,但感觉将一个建筑物作为线程有点奇怪,于是在本次作业中我独立出一个 Distribute 线程用于分发请求,而新主楼仅作为一个整合了诸多楼座的类。

在设计模式上,我在本次作业中同样采用生产者消费者模式,与上次作业类似。

电梯调度策略

本次作业中,我采用 look 加自由竞争的调度策略。

对于纵向电梯,每一个电梯都在上下来回跑,若该方向上没有请求,则改变运行方向。

对于横向电梯,每一个电梯都在绕着楼座跑,若前方两个楼座没有上下电梯的请求,则改变方向。即如果电梯当前处于 C 座,运行方向为 C $\rightarrow$ D ,则先判断 D 座和 E 座是否有请求,如果有,则运行方向不变,否则改变运行方向。

2.4 同步块的设置和锁的选择

在本次作业中,横向和纵向电梯分别通过访问 NewMainBuilding 和 SubBuilding 来获取请求,但我并没有将这两个类中的方法锁起来,而仅仅将最底层的 Floor 类的所有方法锁起来。

这样做保证了增加请求与获取请求的线程安全,即不会有两个电梯获取到同一个请求,也不会在加入请求的时候同时获取请求。但在查询请求时具有线程的不确定性,即一个线程在查询某个楼层是否有请求时另一个线程在往这个楼层加东西,那么查询的结果是不确定的,但这种不确定性只会影响电梯的运行方向,并不会对最终的结果产生影响。而如果我将 NewMainBuilding 和 SubBuilding 的方法也都锁起来,尽管在查询时也具有线程安全性,但是一个时刻只能有一个电梯能访问 NewMainBuilding,失去了多线程设计的意义。

3、homework7

3.1 UML 类图

3.2 UML 协作图

3.3 架构设计

请求处理方式

依据换乘的次数,我将一个请求拆分成多段,保证每个请求仅需要一个电梯来解决,一开始只有第一段请求对电梯可见,即可被电梯处理,在处理完当前请求后,唤醒这条路线中需要处理的下一段请求,使下一段请求对电梯可见。

例如 A-2-TO-B-2 可以拆分成 A-2-TO-A-1、A-1-TO-B-1、B-1-TO-B-2,一开始只有 A-2-TO-A-1 对电梯可见,当完成这段请求后,唤醒 A-1-TO-B-1的请求,使其能够被电梯处理,处理完 A-1-TO-B-1 后,再唤醒最后一段请求。

将请求拆分成多段以后,请求的处理方式同第六次作业。

电梯调度策略

同第六次作业

3.4 同步块的设置和锁的选择

同第六次作业

二、测试策略

1、随机数据测试

随机数据生成

采用 java 的 Random 类随机生成请求类别、起始楼座等信息,再将这些信息整合成一条请求。

评测程序

对电梯以及行为建模,将每一个输出依据输出中的电梯 id 交给不同的电梯进行处理,每一个电梯都记录了该电梯获取上一个输出时候的状态(ARRIVE等字符串信息、时间、楼座、楼层、电梯中的每一个人),将电梯上一次状态与当前状态进行对比,并判断当前状态是否符合题目要求(如是否超载),如果不符合要求,则说明该行输出错误。

2、边界数据测试

  • 同一时间同一地点到达很多人
  • 同一时间不同地点到达很多人
  • 同一时间加入很多电梯
  • 在某电梯到达某一层时对该层加入请求
  • 间隔很长时间没有请求
  • 仅有一个电梯在处理请求

三、bug 分析

在第五次作业中,若某一层有上电梯的请求而电梯却满载且没人要下时,我依旧让电梯开关门,浪费了时间,使得强测的一个点运行超时。修改电梯的开门条件,使得电梯满载且没人要下时不开门,便修复了这个 bug。

第六次、第七次作业的强测与互测均未发现 bug。

四、心得体会

在一开始编写多线程代码的时候,我总是出现线程无法结束、线程之间死锁的现象,被搞得焦头烂额,但在调试的过程中,也逐渐学会了一些多线程调试的技巧,通过在合适的地方进行输出,我显式地看到了多线程程序的运行顺序,对多线程程序的运行有了一个更深入的认识。

在这个单元,我阅读了《图解 Java 多线程设计模式》的部分章节,惊叹于那巧妙的设计思想。在作业中我也使用了其中的部分设计模式。随着三次作业的迭代开发,我也认识到了合理采用设计模式不仅能够使程序的架构更为清晰,也能够使程序具有良好的可拓展性。

posted @ 2022-05-04 09:51  wphos  阅读(33)  评论(0编辑  收藏  举报