码迷,mamicode.com
首页 > 编程语言 > 详细

渐入OO课的深处,探索多线程的秘密——OO第二次博客总结

时间:2018-05-02 02:42:32      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:多个   iss   坚持   解决问题   项目   round   类方法   探索   zed   

一次又一次的挑战,一次又一次全新的知识,我来到了多线程的面前


 

第五次作业

1、度量分析

技术分享图片

 

>第五次作业由于很大程度上调用的是前两次电梯的一些代码,所以存在的问题与前几次也十分相似。同时由于第一次使用多线程来解决问题,可能将某些功能过于集中的放在了个别类中。导致McCabe Cyclomatic Complexity以及Nested Block Depth出现标红的现象。

2、类图

技术分享图片

>这次在类图上面问题体现的也很明显,在方法的分配上并没有做的很平均。这主要是由于为第一次多线程作业,所以将大部分的功能全部赋予了elevator类中,导致类过于冗长而且类图显得特别难看。

3、关于BUG

  当我们在经历了三次面向对象式的JAVA编程历练以后,从最开始的一头雾水到现在的略知一二,笔者以为自己终于已经适应了JAVA的语法与编写规范,但第五次作业的降临又让我有了泰山压顶般的感受。最后一次电梯作业,第一次运用多线程来处理实际问题,学长学姐口中OO最难的一次作业果然名不虚传。直到周二晚上由于对多线程安全的理解不深刻,笔者的程序仍然存在些许小bug。由于精力实在有限,导致最后这一点bug被搁置了。~所幸这次测试的公测还是比较弱的,这次笔者的程序被公测和互测分别找了一个bug。公测的bug仍然在于对多线程的保护上,最终导致在多个电梯共同运行情况下运动量的计算出现了问题(3号电梯运动量被反复计算),导致公测的这一个点挂了。而测试者这次找到的问题同样是由于多线程在运行上的不确定性导致,而这个问题则是反映在了捎带这个功能上面,原本该捎带的一次请求由于多线程完成度的问题导致在条件判断上出现偏差,没有被捎带上。此外没有被找到其他bug。而作为测试者,这次笔者拿到的程序问题还是不少的:首先在公测的格式测试方面,他对于错误格式的判断很完善,缺在输出格式上与要求有一点不同,然后是对于捎带和同质的判断也存在很大的问题,而且他把输出时间输出成了间隔时间,最终导致公测错了很多。不过幸运的是对于最简单的电梯和楼层请求,由于输入时间为0,所以并没有错,也没有达到一个无效的条件。而在公测之外,此人还有很多的细节方面也没有做好。互测上笔者除了报告了他的输出格式错误之外,还对单行20条请求和50行总请求进行了测试,他也没有对此作出相应的错误响应。同时在一层输出多条相同到达信息他也没有处理。总之笔者认为他这次作业还是比较失败的,很多并不难但比较细的东西没有考虑到,而且输出的错误是态度问题,笔者感觉他并没有很认真的对待这次多线程作业。不过这次作业着实比较困难,周围的同学也都多多少少出现了不同的问题,同样这第一次的多线程之旅也给我们带来了不少的反思与经验。电梯的结束意味着新的开始,这次作业的bug就总结到这里咯。


 

第六次作业 

1、度量分析

技术分享图片

>这一次作业由于主要是对文件进行一个操作,所以对于功能无论是从代码量上还是代码难度上都不是特别的难。但在判断文件相对应的操作时需要判断的条件过于繁多,过多的if-else所以造成了程序嵌套程度过深的情况,使Nested Block Depth出现标红。而由于这些主要的判断以及其他的主要功能部分都是在Trigger中完成的,又导致过多的方法集中在了一个类中,使McCabe Cyclomatic Complexity出现标红现象。

2、类图

技术分享图片

 

 >第六次作业的类图还是比较清晰明确的,各个类分工也比较明确。可惜做的不好的一点在上面的度量分析与类图中都可以反映出来,过多的功能性方法都集中在了Trigger这一个关于触发器的类之中,使这一个类特别的突兀。

3、关于BUG

  学长们都说第五次和第六次作业是最难的两次,事实也确实如此。IFTTT,当这个陌生的词汇第一次出现在我眼帘的时候我根本不知道这次作业我们要做的究竟是什么。而OO的魅力大概就在于每一次作业我们都需要自己去学习并探索新的知识,而这次正是对于文件的各种操作与监控。实际上这次作业无论是从代码量还是逻辑难度上看都不高,但难就难在不清楚作业目标以及许多的新操作。不过有惊无险,这次作业的测试中笔者没有被公测和互测找到bug,而笔者测试的程序写的也十分完美。但可能是没有及时收到issue上面的一些规则修改,没有对于超过10个监控对象的处理。readme中也没有响应的说明,笔者也只报了这样一个bug。随着作业的逐步深入,测试方面也变的越来越困难,所以笔者没有时间也由于能力所限无法进行深层的测试,一次相对和平的作业就这样过去了。


 

第七次作业 

1、度量分析

技术分享图片

 

>第一次关于出租车系列的作业,在功能上的描述与编写上并不是很难。但想到并实施一个比较好的架构十分重要而且也不容易。我在深思熟虑之后才开始动工这次的作业,所以在类的分工做的十分的明确,但这个if-else的嵌套深度每一次作业都没有解决。这可能是由于我经验的上的不足,没有很好的利用一些优质的算法与JDK自身函数,导致判断次数与层次过于太多,以后这方面的问题我一定会多加的注意一些。

2、类图

技术分享图片

 

>由于是第一次出租车的作业,所以这次的类图比较简单,从名字上也能清楚的看出各个类的功能与属性。

3、关于BUG

  在电梯之后又迎来了又一个系列性作业——出租车系列作业。万事开头难,虽然已经有了两次多线程作业的经历,但仍然对多线程的理解不够清楚,在设计与实际工作过程中也不是说十分顺利。由于是系列作业,关系到后面几次作业的成败,所以这次作业的bug修改也是极为重要。由于人工手动测试十分困难,所以公测只放了一些输入格式上的一些错误,笔者的程序当然也没有问题。当笔者看到在互测中自己被找到的bug是同质请求出现了没有判断的情况,仔细分析以后发现是虽然在两次输入上实际的时间差是小于100ms的,但由于笔者在对每条请求处理上有些复杂,导致程序运行时间偏长,使程序中两次输入的时间差超过了100ms,没有判断为同质请求,这样是不符合实际的。所以笔者需要对这次代码作出相应优化,或者利用假时间来判断100ms,尽量减小程序运行时间导致的误差。另一个bug则是测试者偶然发现当输入满足一定的条件时我的出租车信用度在计算上会出现差错,虽然现在仍然不知道具体问题是什么,但可以肯定的是bug出现在信用度计算上的条件与位置一块。这就是笔者这次作业被找到的bug。相同笔者测试的程序也存在一些类似的问题:首先笔者的测试任务代码在公测方面没有判断出发点和目的点相同的情况,也就是没有忽略此类请求,这也是他公测唯一的错误。在互测上,首先比较明显的一个问题是当输入请求多于一条时,对方程序的出租车虽然会对所有请求有所响应,但每次都是在接到单之后却不去运动,笔者猜测是他在状态转化上出现了问题,导致出租车出现了不继续跑的情况。对方的第二个bug情况就和笔者的bug类似了,由于我们都是直接使用系统时间(也就是真时间)来进行各种判断与输出,所以每次模拟出租车运行一格200ms实际程序运行超过200ms,所以在输出上会有所体现。因为结果精确到100ms,所以在一定量累积以后这个误差量达到100ms使输出出现问题。而这个由于程序运行时间导致的误差错误笔者在上面自己的bug处也有所提及。

  至此,这三次作业的bug分析之旅也就结束了。


 

 

心得体会 

1.当步入多线程的世界,才知道这里面的路是多么的艰难。这几次作业我觉的最困难的点大致有两个,首先就是针对于一个项目的架构设计。由于是多线程的设计,所以在每次动工之前需要想清楚要建立多少个类,同时需要想多少个线程才能把这个功能做到最佳化。
2.其二就是关于多线程最重要的一环:线程安全问题。在完成代码基础功能之后,如果对线程不加以管控,往往会出现很多不合乎常理的错误,这都是因为多个线程同时运行情况下对公共资源的无管控的争夺,再加上多线程运行的不确定性导致公共资源出现意料之外的错误。所以在功能完成后要对几个线程之间的联系作出分析,比如几乎每次作业都用到的请求队列在输入线程和调度器线程之间的共用,请求的存取就好比消费者与生产者之间的经典案例。需要对之间的纽带——请求队列进行上锁操作,而这就要对所有的共用资源全部分析清楚。当然在一定的实践与理解之后,笔者也意识到并不是所有涉及到共用资源都需要上锁,有的队伍共用资源的调用只是拿到其性质或者其他的东西,并不对其进行操作与改变,这一部分的共用其实是不需要加锁保护的。就针对于请求队列而言,重要的是对存入请求以及取出请求(删除请求)进行保护,否则会出现乱了套的情况。
3.对于多线程代码的调试也是比较有感触的一个部分。它本身的不确定性很大程度上就决定了多线程的调试并不能依靠加断点来单步调试。所以需要灵活而巧妙地运用输出调试来找到问题的所在。而且在每个线程的开始去进行输出标志也是屡试不爽的一个小技巧。同时多线程也有许多的好处,比如多线程可以把任务分块执行,分块后可以同时进行而不用等待。这样效率更高如下载文件,通过多线程就可以实现多文件下载。同时线程安全的实现方式也是有很多种的而我使用的Synchronized关键字:编译后会在同步块前后分别形monitorenter和monitorexit这两个字节码指令。这两个指令都需要一个引用类型的参数来指明要锁定和解锁的对象。如果没有明确指定对象参数,那就根据synchronized修饰的是实例方法还是类方法,去取对应的对象实例或Class对象来作为锁对象。在执行monitorenter指令时,首先尝试获取对象的锁,如果没有被锁定或者当前线程已经拥有了该对象的锁,则将锁计数器加1,相应的执行moniterexit时,将锁计数器减1,当计数器为0时,锁就被释放了。如果获取对象锁失败,则当前线程就要阻塞等待。


 

写在最后

  ~~至此,课程已经过去了一多半,我相信大家都已经对OO和JAVA有了一定程度的熟悉与个人的感受吧。在这里再次对所有在完成作业过程中帮助过我的同学以及认真负责测试我代码的同学表示衷心的感谢。希望大家能坚持下去,一起加把劲,努力去迎接新的挑战与胜利的曙光。

 

渐入OO课的深处,探索多线程的秘密——OO第二次博客总结

标签:多个   iss   坚持   解决问题   项目   round   类方法   探索   zed   

原文地址:https://www.cnblogs.com/imageboom/p/8978170.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!