面向对象第二单元总结

本单元的任务为电梯运行调度问题

三次作业将任务划分三个阶段:    

              傻瓜(FAFS)调度单部电梯  ——>>      可稍带(ALS)调度单部电梯  ——>>     智能(SS)调度多部电梯


 ROUND 1    

 

第一次电梯作业要求我们实现一部傻瓜调度电梯,即只需按顺序满足每个人的需求。由于是第一次接触多线程的问题,这次作业对于我来说,也是一个不小的挑战。模仿课上讲的生产者——消费者问题,我的第一部傻瓜电梯就这样诞生了。

输入模拟器即生产者,生产需求;电梯即消费者,满足需求。这次是一个生产者,一个消费者的问题,且消费者一次只能消费一个产品,我采用的是生产者每生产一个产品,消费者便将其消费,以此类推。即每次从缓存队列中取一个,扔到电梯里,电梯去干活,干完活后再扔下一个人进电梯,以此类推。

从类图中看,这次的结构还是比较简单的,虽然在主线程中开了另一个电梯的线程,但现在想来其实也可以单线程满足这次作业的要求;从复杂度分析图来看,这次作业的算法复杂度也是比较低的。总之第一次作业,大概是让我们小试牛刀,初步了解多线程。

 

 

 ROUND 2

 

 

 

第二次作业的要求是完成一部可稍带调度的电梯,即需要电梯在上下行过程中不仅要完成一个人的请求,而是尽可能多捎带人上下,满足尽可能多的人的需求。说实话,这次作业是三次中我觉得最难的一次,并且也是我花时间最久的一次。形成架构大概花费了大半天的时间,写代码大约半天的时间。

由于这次作业更加接近于现实情况,我就从现实生活中着手,先仔细思考了自己坐电梯的过程。首先我来到电梯前,想好自己要去几层,按下向上或向下的按钮;电梯慢悠悠来到我这一层,接上我,我在电梯里按下想去楼层的按钮;电梯将我送到我的目的楼层,开门,放我出去,再关门,等待下一位旅客的到来。

通过不断分析这个过程,有了一个想法,再推翻它,到再有想法,再推翻,来回往复不停的思考,终于功夫不负有心人,我捣鼓出了一次自己比较满意的架构,也是我自己写了这么多次作业以来自认为想的最好的一次,我的架构如下:

首先这次作业中有三个对象,人、电梯和调度器。人又分为两种,在电梯外面苦苦等待的人和美滋滋已经坐上电梯的人,于是我设计了两个队列,一个是在电梯外面的,一个是电梯内部的。电梯外部的队列为一个数组,每个元素为在这层想要上行的队列及想要下行的队列,一共有楼层那么多个元素,对应每一个楼层;电梯每上一个人,将其从外部队列中删除,加入电梯的内部队列。外部队列归调度器管辖,内部队列由电梯自行管理。通过模拟现实中人上了电梯后要按层数,我在电梯内部建立的一个数组,对应每一层,标记每一个进电梯人的目的楼层,在他们出去后再擦出这个标记。这样,大家各行其是,分工明确,不会相互推卸责任。

 在优化方面,我只做了一个小小的优化,其实与其说是优化,不如说是自己的一种算法,因为往电梯中塞人的时间及楼层都是不确定的,对于每一种算法,只要数据对口,一定能跑得非常快。我的算法是首先电梯上行过程中只能接向上走的人,下行的过程中只能接下行的人,而我认为电梯上行一趟或下行一趟能接越多的人则大概率能跑的越快,因此若电梯里有人,则满足电梯里人的要求,若无,则计算一下是上行的人多还是下行的人多,若上行的人多,则电梯前往上行人中最下面一层,反之前往下行人中最高的一层,之后继续运行。

从类图来看,这次的架构基本只多了外部队列,当然电梯类做了很大的改动,也是复杂度最高的一类。

 

 ROUND 3

 

 

 

 

第三次作业的要求是三部智能调度电梯,且每个电梯能停的楼层、速度及最大载客量均不同。这次作业从一部电梯扩展为三部电梯,并且调度方法由自己设计。这个作业的类型是一个生产者多个消费者的问题。我这次作业花费的时间是上次作业的一半,主要原因在于我沿用了上次的电梯类的代码,加入了载客量的限制,其余基本无变化,每个电梯都有着自己的外部队列,调度器负责往其中分配人员,电梯负责完成自己的外部队列中的请求。调度器的算法是改动比较大的,主要的问题在于有的乘客无法通过坐一次电梯到达自己的目的地,需要换乘,而这件工作,我将其分配给了调度器来完成,我采用的算法比较简单,可以直达的乘客我便将其送入那个可以直达的电梯,若有多个电梯可以直达,则将其送入最快的电梯;不可以直达的乘客则让其换乘一次,先塞入第一个电梯,之后第一个电梯将人送到中转站,再扔回给调度器,调度器再将其扔给第二个电梯。整个程序的停止条件为所有人的请求都得到满足。

这次的架构还是非常清晰的,基本沿用了上次的架构,复杂度最高的是调度器扔人算法及电梯运行算法。

在线程安全方面,我认为线程之间的协同,总的来说就是要考虑两个方面:

  • 同步控制,即线程的执行顺序需要控制,在命令队列为空时,消费者线程 是不能从中取命令的,必须要等待生产者线程放入命令后消费者线程才可以继续执行。
  • 互斥控制,即读-写互斥和写-写互斥。

对于这两方面只要分别针对性的进行控制,线程安全就没有太大问题

 

SOLID原则检查

  • 单一责任原则遵守的自认为不错,每个类都只负起自己该负的责任
  • 开放封闭原则遵守的自认为不错,代码更新无需删除原来的代码。
  • 里氏替换原则:没有使用继承
  • 接口隔离原则:没有定义接口,也没有必要定义接口
  • 依赖倒置原则:未使用抽象类

 

 


Summary

总结一下这个单元三个周的作业,从分数上来看,自己有了很大的进步,在互测中只有一次被找到了bug。我觉得在这个单元中除了学到了多线程的知识,更重要的是我明白了架构的重要性,要先有一个清晰的架构,再动手写,这样会大大减少bug出现的可能性,在没有想法的时候,多想想现实生活中的经历,就像艺术“源于生活,高于生活“一样,我觉得我们现在做的问题也是一样。总之,继续给自己鼓鼓劲儿吧,再接再厉,加油💪

 

posted @ 2019-04-22 17:18  Lisabo  阅读(163)  评论(0编辑  收藏  举报