(一) 设计策略
第五次作业
这次作业是单部可携带ALS电梯。
这次作业我在学习考虑之后选择了LOOK调度算法,采用了生产者-消费者模式。我构造了一个Input类作为输入线程(也就是生产者),同时有一部电梯Elevator类(也就是消费者)接受来自输入线程的请求,它们之间通过调度器Scheduler类共享数据。
第六次作业
这次作业是多部可携带ALS电梯。
这次作业我沿用了上一次作业的架构,逻辑基本相同。在分配电梯的问题上我采用了简单地将PersonID对电梯个数取模的方法,优点是简单而且不易出错,并且最大程度上的继续使用上一次作业的架构。
第七次作业
这次作业是多部可携带ALS电梯。
这次作业架构基本沿袭上次作业。我设计了三种电梯类型ABC类继承Elevator类,他们之间参数和可停靠楼层有不同。为了实现换乘,我设计了TransitPersonRequest类和FInalPersonRequest类继承自PersonRequest类,他们分别是需换乘人员换乘之前的请求和换乘之后的请求。
(二) 设计的可拓展性
功能设计和性能设计
这三次作业我都采用了LOOK算法,以及对ID取模的分配电梯算法。我会直接将请求分配给单部电梯,而其他电梯不会去管这个请求,这相比于某些同学的“电梯抢人”方法,可能不占好处,但却是清晰有效的。我的算法和设计可能不是最好的,但确实在三次强测中都取得了不错的成绩。
设计原则分析
满足开闭原则;里氏替换原则体现的并不明显但是却是满足的(需要使用继承的地方不多);其他原则大体上也是满足的。
(三) 度量分析
第五次作业
UML图
复杂度分析
第六次作业
UML图
复杂度分析
第七次作业
UML图
复杂度分析
(四) bug分析
三次作业在互测中均未发现bug,我讲一下自己设计过程中遇到的bug。
第五次作业
对于锁的使用并不清楚熟悉,导致出现了MonitorIllegal的情况。
没有使用线程安全容器,抛出异常。
第六次作业
某些电梯线程不能正常结束。原因在于如果某部电梯分配到乘客,而其他电梯接到乘客并且把所有乘客之后,按照我的算法这部电梯会一直等待下去。
解决办法:在电梯线程结束的时候notifyAll通知还未结束的电梯线程结束,同时在wait的附近增加break语句判断结束while循环。
第七次作业
关于换乘的请求处理出现问题,某些情况不能正常结束。在产生换乘的第二条请求时,其他电梯由于发现没有乘客就已经结束了,而这个换乘的请求会加入到已经结束的这个电梯中,导致该乘客一直无法到达终点站,这个电梯也一直无法结束。
解决办法:增加对于换乘人员的计数器,在换乘人员为0的时候相应的电梯线程才能结束。
(五) 发现别人bug用的策略
本人比较佛系,在有评测机的情况下也没想过hack别人的bug。可能因为三次作业都在A屋,在我发现别人也没hack成功的情况下,而且多线程具有很大的不确定性,复现bug有时候完全靠运气,所以我没有hack别人。
多线程编程有太多需要注意的地方,数据共享,线程结束,死锁。
只能说我这几次作业运气都比较好,才取得了96+的成绩,这也让我意识到,一味地追求性能是不行的,设计出一个好的架构,不出bug,那就已经很成功了。