OO第二单元总结
一、程序设计架构
总体架构
三次作业总体架构保持一致,在初始架构的基础上进行增量的迭代开发。
第一次作业
需求:模拟多线程实时电梯系统,每座固定一部纵向电梯,处理同楼座移动请求。
代码框架:
本架构采用生产者-消费者设计模式,托盘为各楼座等待队列,为每座定义了两条等待队列,根据起点至终点的方向不同分为上行队列与下行队列,简化了电梯方向判定的算法。
代码规模:
第二次作业
需求:模拟多线程实时电梯系统,每座初始各一部纵向电梯,可增加纵向电梯与横向电梯,处理同楼座、同楼层移动请求。
代码框架:
代码规模:
对 TimableOutput 封装为OutputThread类,避免出现输出时间戳非递增的情况
第三次作业
需求:模拟多线程实时电梯系统,每座初始各一部纵向电梯,一层一部横向电梯,可增加纵向电梯与横向电梯,处理同楼座、同楼层移动请求以及换乘请求。
代码框架:
代码规模:
第三次架构与第二次基本相同,主要修改在调度器部分,增加了换乘相关操作的方法。
可扩展性分析
-
第一次作业中将电梯相关属性保存在电梯类中,后续作业自定义电梯属性时便于修改。
-
将电梯的每个操作,以及状态判断(是否开门、是否转向等)都抽象出行为方法,逻辑清楚且出现bug时易于修改。
协作图
二、同步块与锁
同步块
-
仿照上机练习代码,建立了一个线程安全类
RequestQueue
,实现安全增加、修改、取出请求。
-
封装输出安全类
OutputThread
,避免出现输出时间戳非递增的情况。
锁
三次作业中,我都选择了使用关键字 synchronized
修饰的锁机制。
-
在
RequestQueue
中对方法上锁,实现队列修改的线程安全。 -
在
Elevator
和Velevator
中对访问的公共队列上锁,防止访问引发线程冲突。
三、调度器设计
在前两次作业中,调度器的核心功能极为简单,即充当“托盘”的作用,接收请求,并分配到候乘表队列中。
第三次作业增添了换乘操作,调度器多了一个“分解”请求的作用,即把换乘请求分解成多个简单请求,这样保证了电梯类只需较少改动,就能完成换乘的要求。
在请求接收方面,采取自由竞争的策略,优点是不需调度器从电梯获取信息,降低耦合性;但有可能会导致电梯接收到不能处理的请求(目标层座不可达),此时需要将请求吐出。
四、DEBUG与测试
第一次作业:
强测出现两个RTLE错误,主要是因为结束时没有判断电梯内是否清空,导致电梯线程没有结束。
第二次作业:
由于未封装输出模块,导致强测出锅,未进互测。
在debug过程中对输出模块进行了封装。
第三次作业:
强测出现两个RTLE错误,一个是纵向电梯中转向函数的缺陷导致,另一个是横向电梯吐出请求的函数,在队列中有多个需要吐出的请求的时候会死循环。
互测无bug。
三次作业中,均采用测评机+构造数据相结合的方式进行测评。
五、心得体会
-
本单元的设计关键之一在于设计线程安全类,使线程尽可能少的处于临界区之中,保证线程安全;使用锁互斥来解决访问冲突。
-
工程设计中要坚持SOLID原则,尽量保证类的功能单一,不承担过多的职责,比如调度器只负责分发请求,电梯只负责解决请求等等。
-
在电梯策略方面,我从始至终使用的都是LOOK策略,虽然性能比较平庸,但代码出锅概率也下降了很多。
-
通过本单元学习,对多线程、共享资源、线程冲突等概念有了较为全面的的一个认知。有了上个月的经验,虽然电梯单元难度较上单元更大,但是工作进程较上单元顺利很多,没有再出现压着ddl提交的情况,可惜有一次未尽互测,以及自动化测试做的仍不够好,希望下单元能再接在厉。
标签:OO,总结,请求,队列,作业,电梯,线程,单元 来源: https://www.cnblogs.com/taosuozi/p/16218635.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。