OO第二月作业总结


写在前面


  第五至第七这三次作业,主要的内容都集中在多线程上。从认识多线程到写多达100+线程的多线程程序,不得不说,刚开始的感觉比在完全不了解java语言第一次写oo作业都要绝望……现在回过头来想,当初刚接触线程的困惑主要就是集中在多线程的概念上。毕竟从来没写过多线程程序,在短期内掌握多线程还是需要一定的过程。三次作业磨练下来,每次作业对多线程都有更深的体会。

第五次作业


  这次作业可谓血淋淋的教训:在前两次作业的基础上用多线程实现多部电梯同时运行。前两次作业中,自己调度器的结构是用队列来实现的,并且每执行完一条指令都需遍历一遍队列来确定下一条主指令以及其捎带指令。这样做得弊端就是代码冗长,维护困难;同时执行效率极其低下。尽管这样的结构让我在前两次电梯作业中取得令自己满意的评测结果,但这般的结构还是令自己不太满意,于是在第五次作业里决定改变调度器结构:模拟现实生活中的电梯,每一个电梯有20个楼层按钮,每一楼层有两个上行或下行按钮。这样的结构让同质以及捎带指令的判断变得极为容易,所以在前期写程序时显得“游刃有余”,具体类图如下:

类图

度量图

时序图

  本次作业由于第一次写多线程,又因为结构的问题导致了自己无效,所以时序图就不贴了。(捂脸)
  由以上两图可看到,第五次作业的代码可谓是“一团浆糊”,无论是结构还是度量。造成这种问题的根本原因是在第五次作业中临时打算更换结构,这也使得上次作业的一部分类在这次作业仅仅作为父类存在,毫无作用。同时,由于在更换结构中欠考虑,在程序后期关于主指令的选择仅仅通过按钮已无法实现,加上第一次写线程,最后落得了无效的结果。

第五次作业心得

  尽管第五次作业无效,但我认为在这三次作业中,第五次作业给我带来的收获却是最大的:

  • 如果一次作业是在前几次作业的基础上写的,那么不要去轻易重构。除非你有非常充足的时间,否则在短时间内很难考虑全面要解决的问题,最后很可能会因为时间不够而无法完成一些功能。
  • 虽然第五次作业无效,但这次作业让我对多线程的了解有了一个很好的入门——可以说这次作业花在线程了解以及上手写代码的时间是对半分的。在此插一句,自己在了解多线程时看到一篇知乎上的多线程介绍的文章,感兴趣的朋友可以点击这里查看这篇文章。
  • 在没想清楚自己的程序结构以及没考虑清楚自己的程序怎么写之前千万不要着急上手写代码。

第六次作业


  在写第六次作业之前,听上一届的学长学姐说这一次作业的是最难的一次;在周五的课上吴老师也讲到这几次作业的难度将会是一个峰值。所以,本着越难就得越早开始写的心态,在周末就开始浏览指导书。于是,便有了下面的心路“历程”:

  • 第一次浏览:啥玩意儿??? 这次作业到底要干什么???要输入什么???怎么一会儿控制台一会儿又测试线程的,什么意思???
  • 第二次精读:哦,大概意思是实现文件监控;等会儿,还要监控目录;哎不对,到底是监控文件还是目录???控制台决定启用哪些线程,测试线程实现文件操作来让程序响应。
  • 第n次精读+第n^n次查看issues后:嗯,这次作业的目的还是很明确的,至少从个人角度来看,比上次作业明确不少:每个触发器对应一个线程类实现监控,mission类根据控制台的要求实现向文件写入结果或recover操作;ThreadFile对应知道书中的SafeFile类,里面提供的上了锁的方法用来给测试者提供相应的文件测试线程的代码。Main为程序执行入口。这样一来,有了明确的目标,写起来感觉十分“顺畅”。

  因为事先花了大量时间构思,在写程序中除了一些特定操作的实现卡了一下以外,其他的基本没什么难题。类图如下:

类图:

度量图

时序图


  从度量图中看到,Main类的复杂度较高,这主要是因为在main里对控制台输入进行了处理,并使用了多个for循环(非嵌套)对线程与输入进行匹配并启动。所以在以后的作业里将输入处理放在inputHander类里,能一定程度上减小复杂度。

bug分析

自己的bug

  本次作业自己总共被挑出了四个bug:其中一个为同质指令的监控未忽略;此外,当同一目录下有相同的两个文件时,若执行rename操作,我的程序会识别为path-changed,这也导致了其余的bug。

别人的bug

  首先,公测提供的样例先测着;之后再测一下自己写程序过程中遇到的bug以及相应测试例子。一般三个左右就不再测了,就算有很重要的问题,会在bug说明里阐释——毕竟大家写oo也挺不容易的hhhh。

心得

这次作业给我的感觉跟第二次作业很像:目标明确,写起来行云流水,很是畅快。当然,后来想想,可能心里暗示上有加成吧:这次作业以前就听到说这次是最难的一次,而且舍友的梦拓——一位很大佬的学长——唯一一次无效作业就是这一次。所以在一开始对这次作业便持着最严肃的态度来完成,也因为此,本次作业完成地令自己较为满意。


第七次作业


  是的,你没看错,在写这一次作业之前,又双叒叕听到学长学姐说这次出租车是最难的一次,内心的那个奔腾处理器啊~~~不过也好,听说到这么难以后还是会像第二次作业一样以严肃的态度对待这次作业。和上次一样,周末便开始阅读指导书。
  这次指导书没有上次那么难懂,但精读之后,我个人感觉还是上次作业好写一点………………但要说代码量,确实比不上上次。这次作业个人感觉最主要的就是两点:

乘客请求的处理。

  乘客请求的处理无非就是一个生产者消费者的模型,乍一看貌似没啥可说的。但除了要实现线程输入以及格式的判断外,与助教提供的GUI相结合、每个请求一个线程还是所有请求一个线程、请求抢单窗口的实现等等都需要经过一番谨慎的构思才行。

出租车下一个点应该在哪里的问题,分为两部分:

  • 等待服务状态的下一个点应该为随机。指导书上关于这里写的是满足一定分布规律,经查阅issues后了解到这句话的意思是当处于等待服务状态时,要满足随机行动,意思就是说不能一味地向某一固定方向“随机”。此外,还要考虑是否有路以及边界问题。
  • 服务状态时,要满足最短路径原则。好在助教提供的gui里有一个类似算法,将此算法适当使用后可解决。

类图

度量图

时序图


  从度量图中可以看到,调度器线程还是很“臃肿”,这主要是因为在run方法里使用了两个for循环,第一个for循环作为抢单窗口,其中嵌套了一个对100辆出租车遍历的for循环;第二个for循环分配抢单窗口已经关闭的指令,其中也嵌套了一个对100辆出租车遍历的for循环。

bug分析

  这次被挑两个bug:

自己的bug

  • 未判断起始点与目的地相同的指令。
  • 处于服务状态后每走过一条街道的时间不是200ms。

  关于第二个bug,应该是找下一地点的算法还是不够高效,使得运行时间过长。但经过修改,仍旧有该问题,目前仍在debug中。

第七次作业心得

  每个人都有自己不同的理解,比如有人会认为第六次作业更难,有人会认为第七次更不好对付。一般这些也只能作为一个参考,听到难了也不要想着这次肯定难得自己做不出来了;听到简单了也不要想着肯定没问题………………总之每次作业都像这两次作业一样去做就好。

猜你喜欢

转载自www.cnblogs.com/T-shuo/p/8976104.html