OO2021 - 第二单元

2021面对对象设计与结构 - 第二单元

第5次作业

本次作业的目的是模拟单部多线程电梯的运行。实话说,第5次作业的难点不多,可是由于当时是第一次接触多线程,所以代码的结构设计一直都有问题,改了又改,甚至最后都是卡点过的。

UML图

image

锁与同步块

在整个作业中,有两个的对象在调用时是必须使用同步的,那就是waitingQueueprocessingQueue。而会调用到该对象的线程有 WaitingThreadProcessingThreadElevatorThread。为了预防死锁,在设计代码的时候,尽可能地避免了同时synchronized一个以上的对象。

调度器

因为本次作业中,只涉及单部电梯,所以所有乘客抵达后,请求都会放入到waitingQueue中,而电梯载人的方式是以电梯移动的方向优先,寻找有人等待的楼层加载至processingQueue中,让电梯去载送。当电梯到达目标楼层时,若该楼层有乘客,则以乘客的目标楼层为标准,选择承载的乘客,直至该楼层的等待乘客数为0或电梯的容量达到上限。

分析Bug

由于当时时间紧迫,来不及调试就匆匆提交了(庆幸的是至少过了),导致强测中被hack了4个点,而且整体来说性能分也是偏低的。所以在Bug修复的时候就发现了一个大问题,就是电梯在满客的状态下依然会去载客,这让电梯不断毫无意义地在几个楼层之间移动,导致电梯的效率也大大地降低了。

第6次作业

本次作业的目的是模拟多部同型号电梯的运行。和上次的作业相比,其实本次作业的难度跨度并不大,只要把调度器的分配算法写好,就能很轻易拿到AC了。

UML图

image

锁与同步块

在整个作业中,由于会有多部电梯同时在运行,所以会有多个processingQueue,每个都对应着一个正在运行的电梯,和一个共享的waitingQueue,存放的是还在等待的乘客。所以每次电梯在移动或开关门的时候,都必须先synchronized (waitingQueue),并向waitingQueue更新一次。

调度器

首先,调度器在检测到有乘客请求的时候,会先寻找一个最合适的电梯(最空闲或者会经过乘客起始楼层的电梯),让该电梯去载人。而电梯开门后的操作和上个作业类似,以乘客的目标楼层和电梯的移动方向为标准,选择需要乘载的乘客,直至该楼层的等待乘客数为0或电梯的容量达到上限。

分析Bug

在强测和互测中,都没有发现什么大问题,只是在强测中,有几点的性能分还是差强人意的。这表示调度器的算法还是不够完美的,还是有几种情况是欠缺考虑的。例如在电梯开门时,不应该让尽可能多的乘客上电梯,而是应该先判断有没有比此电梯更适合的电梯,才决定是否要让乘客上电梯的。

第7次作业

本次作业的目的是模拟多部不同型号的电梯运行。在本次作业中,由于电梯型号不同,可停靠的楼层不同,导致我算法和分配上出现了一个严重的问题,幸好最后都顺利解决了,也顺利拿到了AC。

UML图

image

调度器

首先先说调度器(因为困扰我许久的问题就是和调度器有关)。由于会有多部不同型号的电梯同时运行,所以我先建了一个arrivingQueue来存储所有抵达乘客的请求,之后才让Dispatcher逐一分配给合适的电梯来完成请求。可是问题出现了,如果有同型号的几部电梯同时在运行呢?我应该如何让Dispatcher在允许换乘的情况下,将乘客分配给最适合的电梯呢?所以最后我决定不让Dispatcher来分配乘客给电梯,而是将乘客分配给各电梯型号的等待队列里,让电梯自行选择该乘载的乘客。

锁与同步块

显然需要同步和共享的对象有arrivingQueue,三种型号的waitingQueue和一个用于统计是否该让电梯结束允许的prNum

由于在这里会有多个电梯共享一个waitingQueue的情况,并且每个电梯都需要多次占用并读取waitingQueue,所以为了防止其他电梯因为长时间无法占用waitingQueue而导致效率降低,我使用了一种机制就是若电梯只是想要读取waitingQueue而不会对waitingQueue做任何改动时,则将waitingQueue 复制多一份后便释放,让其他电梯有机会调用waitingQueue并防止电梯之间长时间相互等待。

分析Bug

在结合了前两次的经验后,不得不说本次作业使用的调度算法还是很让人满意的,无论是在强测还是互测里,也有可能是我房间里的成员太冷漠,根本没测

心得体会

认真地说,虽然一开始刚接触多线程的时候,真的快被多线程搞疯了,完全不知道该synchronized哪个对象,也不知道为什么代码里会出现死锁,可是不得不说在第7次作业的时候,感觉自己已经掌握了多线程的使用方法时,真的觉得多线程好强大,还是值得我们好好学习的。

还有一点就是在第7次作业中,我发现其实如果能把调度器写好,其实不换乘也能拿到很高分的。事实证明了“不换乘不一定不好”,而且最主要的是换乘的算法真的很难写,也复杂很多(裂开)。

posted @ 2021-04-26 16:12  Xuann  阅读(71)  评论(1)    收藏  举报