OO第二单元总结

一、三次作业的设计策略

 1.第一次作业

  在第一次作业中我们的任务是实现单步多线程傻瓜调度(FAFS)电梯,且只考虑正确性,因此第一次电梯的设计比较简单。我们完全可以按照生产者消费者模型进行设计,这也形成了之后设计电梯的框架,一个inputHandler(输入接口),一个elevator(电梯类),一个dispatcher(调度器),还有一个main(主类)。inputHandler相当于生产者,elevator相当于消费者,在dispatcher中创建一个ArrayList类型的请求队列作为托盘,生产者消费者中同时只能有一个人改变托盘的状态,这就是大概的设计。在这次的傻瓜调度中,相当于生产者每次只生产一个,消费者每次只消费一个,按照这个规则来实现电梯的运作。

 2.第二次作业

  在第二次作业中我们的任务是实现单步多线程可捎带调度(ALS)电梯,这次加入了性能的考察,因此需要一些设计上的技巧。对于捎带问题,我的解决措施是在电梯运行到每一层的时候看一下当时请求队列里有没有在该层上电梯或是下电梯的人。我们依然按照消费者生产者模型进行设计,沿用第一次作业中的4个类,但在电梯类和调度器类要做出一些改动,电梯类需要改变楼层,以及其具体的运行方式(考虑捎带);调度器类增加一个在每一层楼进行遍历请求队列并返回该层对应的请求列表的方法。凡是对于请求队列的修改操作,均需要做到互斥。在这次的可稍带调度中,相当于生产者每次只生产一个,消费者每次消费一个或多个,按照这个规则来实现电梯的运作。

 3.第三次作业

  在第三次作业中我们的任务是实现多部多线程智能调度(SS)电梯。我们依然按照消费者生产者模型进行设计,沿用第一次作业中的4个类。为了避免我们设计的固化,增加程序的可拓展性,这次对电梯的一些参数进行了修改,如可停靠楼层,每层的运行时间以及最大载客量等,这就需要我们在创建新的电梯对象时能够将这些参数赋给新电梯,因此需要在电梯类中对构造函数进行修改。而其他的因为在第二次电梯中已经实现了方法的互斥,即使消费者数目增多,也不会造成请求队列的混乱。但由于电梯停靠楼层的问题,需要考虑乘客的换乘,即请求的拆分。完成这几步,我们的第三次作业就完成了。

二、程序结构分析

 1.第一次作业

  (1)类规格分析

 

    这次的作业中,无论是从每个类的代码量,还是总的代码量都比较短,更多的是为了我们初次接触多线程时候理解多线程的工作模式。

  (2)方法复杂度分析

  

    从方法复杂度来看,也没有任何一个较复杂的方法。

  (3)类图

    类图可以非常明显的看出几个类之间的依赖关系,在主类中创建了“生产者”,“消费者”和“托盘”,然后按照生产者put,消费者get的方式进行信息的传递,put和get的方式也较为单一,都是直接对托盘的单一操作。

  (4)UML分析

 2.第二次作业

  (1)类规格分析

    这次可以看出,代码量明显增加,这主要是由于elevator这个类中增加了捎带功能导致的,内部增加了请求队列,需要不时清空请求队列,以及查看是否满足捎带条件等。

  (2)方法复杂度分析

 

    从上图可以看出,总的方法复杂度依然不是很高,但其中有一个方法(clearList)的复杂度很高,分析其原因,其中用了非常多的条件判断语句和循环语句,是因为当时做了一个比较naive的优化,在清空请求队列时判断了最高层楼和最底层楼,然后根据当前楼层位置来决定运行方向,这就导致其中有非常多的判断。

  (3)类图

    类与类之间的关系与第一次作业几乎完全相同。

  (4)UML协作图

    与第一次的协作关系中,第二次作业只是多了一个捎带这一与get和put互斥的操作。

 3.第三次作业

  (1)类规格分析

    这一次代码量较上一次又有所增加,分析其原因,elevator为了避免设计的死板,增加了每部电梯互异的停靠楼层、载客量、运行速度等属性,这就导致dispatcher中在下发请求时需要考虑得到请求的电梯能不能在对应层停靠,elevator在捎带时也需要考虑能不能在该楼层停靠的问题。

  (2)方法复杂度分析

    这次的作业中总体复杂度有所提高,这是由于在和捎带相关的方法中,都需要进行多重的条件判断。

  (3)类图

    类与类之间的关系与前两次相同。

  (4)UML协作图

    

    除了增加了电梯的数量,其他与第二次相同。

三、bug分析

  第一次和第二次作业中,我的程序均未在公测或互测中出现bug,但是在第三次作业中,我的程序出现了严重的bug,时常出现超载的情况,这是由于在我处理主请求到达目的楼层前,可能已经捎带了过多的乘客,这个bug的出现是调度方案的问题而不是线程不安全,在修复时将捎带方法中的捎带上限减小一个即可。

四、bug发现策略

  直接阅读每个人的代码太过繁琐,因此我采用的是借助大佬的评测机,跑就行了,遇到bug自然就停了。

五、心得体会

  多线程一个明显的现象就是bug难以复现,一个线程安全出现问题可能要十几次或许才能复现,死锁等问题倒是可以通过使用jprofiler轻松解决,所以要在设计的时候考虑好共享对象的加锁问题,尽量避免之后去发现bug。

  在三次作业中我使用的都是同一个生产者消费者模型,从第一次的设计到最后一次的设计都只用了4个类,这就说明了一个合理的架构的重要性,在设计之初多思考,尽量保证程序的可拓展性,这样会使接下来的工作更轻松。

posted @ 2019-04-24 15:54  胖胖的毛毛虫  阅读(183)  评论(0编辑  收藏  举报