OO第二单元总结

OO第二单元总结

  开始之前,先感叹一句,Multithreading真的蛮难的!

第一次作业

  第一次作业任务为一步可稍带电梯运行的模拟。

类关系图:

  本次作业使用Main类负责接收新请求、创建缓冲区、创建并启动电梯线程;Buffer类负责缓冲存放新来的请求;Elevator类负责对请求队列进行可稍带的处理,首先处理主请求,之后判断是否可稍带进行后续请求处理。

 

同步块与锁的设置:

  每当电梯对象需要将缓冲区(控制器)中的PersonRequest从requests列表取出时(即需要更改requests时),将requests使用 synchronized 同步锁 上锁,例如:

  当缓冲区requests处理完但之后还会有请求时,调用buffer.requests.wait()让其进入等待阻塞状态:

  直到有新的request输入,此时在Buffer中唤醒全部因requests被阻塞的线程:

  实际上,该缓冲区作用类似于 生产者消费者模式 中设置的缓冲区,解决了并发和忙闲不均的问题。

 

bug分析:

  第一次作业bug出现在对Night情况处理中产生了RTE,捎带的策略为判断经过楼层的PersonRequest是否和主请求电梯运行方向相同,因此对Night情况增加了特殊处理(首先接到最高层需求乘客)即解决了该问题。第一次作业只有一个运行中线程,未出现死锁问题。

 

发现bug策略:

  对于单电梯,着重注意测试Night情况超时,设计请求出发层数随时间增加而变大。

 

第二次作业

  第二次作业任务为三步到五步可稍带电梯运行的模拟。

类关系图:

  本次作业较上次增加了一个处理ADD电梯请求的新类,可以调用其中addElevator方法创建新电梯对象并启动对应线程。

 

同步块与锁的设置:

  因为作业一设计时已考虑了增加电梯时的情况,因此第二次作业同步块的设置和第一次基本相同,仍然是相同的处理方式。

 

调度器设置:

  因为沿用了 生产者消费者模式 的缓冲区,因此对于多部电梯,其最先处理的即为buffer中位于requests列表中第一个的PersonRequest(将其作为得到该请求的电梯的主请求)。

 

bug分析:

  本次bug主要出现在增加电梯后处理请求产生Real Time Exceed,即未在210s内完成优化策略后可实现的全部运行,作业保证了电梯调度的正确性,但未能满足性能的高效。

 

发现bug策略:

  因为本次强测分数并不理想,因此组内成员一定也有超时、性能分低的问题,所以着重测试因策略不优化而造成的RTE问题,仿照强测点9,在150s后再给出一些距离较远的上车乘客的请求,要求对策略的优化。

  本单元发现的bug情况较第一单元差距最大在于对线程间交互的测试,不同于单线程的多项式求导,多线程要求1.不发生死锁 2.调度策略有效,因此这两项也是构造测试点前着重考虑的测试问题。

 

第三次作业

  第三次作业为多部不同型号电梯运行的模拟。

类关系图:

  第三次作业增加了Controller类负责对电梯进行路径计算、调度,利用Person类建立电梯中全部乘客列表。但因为Controller的调度问题,本次作业未能通过中测。

 

心得体会

线程安全:

  一个对象是否是线程安全的,取决于它是否被多个线程访问。当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。

  为了降低锁的竞争,可以 缩小锁的范围 :将与锁无关的代码移出同步代码块,尤其是开销较大的操作以及可能被阻塞的操作(IO操作)。即我们应该只在可能存在多个线程共享访问冲突的地方使用锁:1.保证所有可能存在的多个线程共享访问的地方都加了锁。 2.保证只在必要的地方加锁,尽量缩小锁的范围。

 

层次化设计:

  对于层次化设计,通过本单元的两次上机,依次了解了调度器线程池 的多线程编程模式,也将其思路使用到了几次作业中,因此本单元的上级实验设计得相当不错。

 

  至此,OO课程已过半,希望能再接再厉,更好地完成三四章节的学习。

posted @ 2021-04-27 16:44  chidwick  阅读(77)  评论(0)    收藏  举报