OO第二单元总结

一、同步块的设置和锁的选择

     由于本单元作业采用集中调度的方式,因此不同线程的共享资源仅为请求队列, 故同步块设置在选取主请求时、电梯进人时,锁住请求队列即可;此外,在第三次作业中,由于有可能有换乘的存在,在电梯乘客出时,要判断乘客是否到达了终点,若没有,则应设置一同步块,锁住请求队列,并将该乘客请求作适当修改加入到请求队列中。

二、调度器的设计

     以ALS调度策略为基础,我采取了集中调度的形式,电梯内为空时,各个电梯自由竞争主请求,以主请求方向作为运行方向,每到一层,设置一同步块,电梯遍历所有请求判断是否有可捎带请求,有则移除该请求,将其置入电梯内部队列中。并捎带途中遇到的与主请求到达方向相同的请求;电梯不为空时,电梯选择电梯内到达最早的请求为主请求,捎带策略与上相同。因此我并没有专门的调度器类,这样的架构是较为愚蠢的。

三、功能设计和架构设计

UML类图

UML协作图

可扩展性分析

     在第三次作业中,我对于三种电梯分别定义了三个类,每个类中包含了电梯的调度策略、乘客进出方法等等,代码存在较多的重复、冗余,如果电梯的调度要求出现变化,则需同时修改三个电梯类,因此我设计的可扩展性比较差。一个可行的优化方法是对于电梯的调度策略另建一个类,电梯调用相同策略时就可大量减少代码量。但由于电梯种类的不同导致其对于主请求的选择也有要求,因此最好的优化方式还是设计一调度器,为每一电梯设计一请求队列,调度器分析请求最适合哪一个电梯执行,再分配给电梯内请求队列执行,如此可实现自由调换策略,减少冗余代码。

四、bug总结

      无论是自己调试过程中,还是查看公测结果,bug总是无处不在的(这也和愚蠢的架构有很大关系),现选出几个较有意义的分享:

  • 选取到主请求后,无论其是否进入电梯,都应在第一时间内将其移出请求队列,防止其他电梯选取到该请求;
  • 在第三次作业中,即使请求队列内有请求,部分电梯型号也可能无法接受这些请求。因此获取主请求时,如果先判断总队列有是否符合条件的请求,后判断电梯里是否有人,就会导致若总队列里无符合条件的请求,则电梯里的人也无法被正常送到终点;因此应将判断顺序调换;
  • 第三次作业电梯线程如何停止的问题,不能单纯像前两次一样,电梯无人、输入结束、请求队列无人就可停止,因为有换乘的存在,其他电梯也可产生请求,如果能运送该请求的电梯停止了,该请求将永远无法满足;为此我设计使A电梯最终结束,以静态变量stopRunning为判断依据,其他电梯停运后使该变量加一,当其他所有电梯静止时,A电梯方可结束运行。

五、测试策略

  • 根据自己可能比较通性的bug,设计针对性的测试样例。
  • 对每个到达模式,设计较为极端的测试样例,如一次输入较大量数据;在电梯静止较长一段时间后输入较多数据。

六、心得体会

     本单元主要侧重多线程的设计,着重强调线程安全,电梯的调度策略则是八仙过海,各显神通。第一次作业时,由于对多线程的陌生,导致事倍功半,最终未来得及de完bug,之后为了能够简便地完成作业,选择了集中调度,电梯自由竞争的方式。这虽然简化了逻辑,却使得第三次作业代码大量冗余,可扩展性极差(幸好不会有第四次作业了),足可见一开始就有良好架构的必要性。此外,线程的安全也是时时刻刻不能忽视的,我由于全程仅有一个锁(请求队列),因此不会出现死锁的问题。但也因为对于多线程的考虑不周出现了很多bug,导致人出现了“分身”的情况。其实对于此次作业,任何对于请求队列的访问、操作,统统设置同步块锁住是比较保险的。

     日后对于多线程的设计,动手前一定要考虑好线程间的共享资源、交互关系,考虑到可能产生的冲突,方能达到事半功倍的效果。

posted @ 2021-04-27 20:02  张什么来着  阅读(75)  评论(0)    收藏  举报