OO第一单元作业总结——Java多线程电梯调度

  本单元主要通过电梯系列习题培养同学们的多线程编程能力,难度逐步递增。第一次最为简单,第二次、第三次则相对困难。我个人在三次作业中均使用wait与notifyAll来解决线程暂停与运行,三次作业架构基本相同,通过在类中增加不同方法来实现不同功能:思路清晰,大大简化了编程难度。

一、作业总结及度量

第一次作业

  本次作业较为简单。在写本次作业之前我在网上通过Mooc学习了Java多线程课程,通过熟悉、理解最经典的生产者消费者模型再稍加修改基本上就可以完成本次作业。传统的生产者消费者模型仓库大小为N,甚至本次作业可以把仓库(电梯)大小设置为1即可通过。但为了下次更方便的扩展,以及深入学习Java多线程,我选择使用了wait与notifyAll,再之后的几次作业中也以此为基础进行实现。

  主题架构为Input与Output俩个线程,俩个线程都继承与runnable接口,Input线程在任何时候都开启,可以实时判断当前输入是否合法,并把合法输入放进共享对象Person中。每当共享对象队列为空,则Output线程wait,Input线程每放入一个合法输入则notifyAll来激活Output线程。当输入结束时,Input更改共享对象Person中的flag为false,来达到关闭俩个线程。

类图:

方法图:

第二次作业

  本次作业在第一次作业的基础上,在Elevator(第一次作业的Output)类中增加了elevator队列,来判断当前电梯内是否有人。每当elevator为空,则从Person队列中读取第一个请求为主请求。在电梯去接主请求的过程中,每到一层判断当前Person中是否有与主请求方向相同的请求,如果有则放入elevator,并判断这一层时有否有人可以下电梯。电梯会一直往同一个方向运动,直到elevator为空。

类图:

方法图:

第三次作业

   本次作业在第二次捎带的基础上,将Elevator线程增设至3个线程,并在Elevator类中增加了一个需要传递给别的线程的传递队列。如果当前请求可以通过一辆电梯来完成则将其放入对应线程,如果不行则判断通过那俩部电梯可以完成运送,并把当前请求拆分为俩个请求,分别传入第一部电梯的调度队列和传递队列,等第一部电梯完成自己的调度后将传递队列中对应的请求传给相应电梯请求队列,来达到防止第一部电梯请求还未完成,第二部电梯就将该请求送至目的地的情况发生。

类图:

方法图:

二、分析自己程序的bug

  本次作业的bug主要集中在1、线程关闭,2、线程暂停与开启。

  1. 线程关闭问题,我一开始使Input线程每读进一个请求就wait,意外在多线程的架构下实现了单线程,每次只会有一个线程激活。
  2. 线程暂停与开启问题,由于第三次作业的线程较多,如果直接使用前俩次作业的暂停或开启方法,会导致传入请求却无法输出的问题,需要在多个地方加入notifyAll。

三、发现别人bug时所采取的策略

  本次作业我们班合作实现了评测机。通过shell脚本语言为基础,python实现随机请求的生成,以及输出正误的判断实现了评测机,在互测中大大提高了de别人bug的能力。

四、心得体会

  多线程编程可以说是大多数java程序员的立命之本,而多线程看起来容易,实际上也是颇有难度的。首先他不好debug...很多时候java多线程的bug很难复现,另外即使bug能够复现在自身对java多线程认识不足的时候也很难判断出到底怎么修改。我还是感觉自己对于java多线程的认识远远不足,回头还需要多看些相关书籍完成些相关练习来加深理解。听说之后两个单元会通过出租车问题加深我们对于多线程的认识,这很让我期待。

最后感谢老师、助教在这个单元给予我们的帮助和指导!

附:

一个介绍UML语法的个人认为较好的博客链接:https://blog.csdn.net/zh_weir/article/details/72675013

猜你喜欢

转载自www.cnblogs.com/HobbitByDyk/p/10759108.html