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

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



第五次作业

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有了一定程度的熟悉与个人的感受吧。在这里再次对所有在完成作业过程中帮助过我的同学以及认真负责测试我代码的同学表示衷心的感谢。希望大家能坚持下去,一起加把劲,努力去迎接新的挑战与胜利的曙光。

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

时间: 2024-10-12 19:06:02

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

OO第二次博客作业(2018春)

写在前面 多线程 搞死人 第五次作业 类图: 这次作业的调度器(als_3_controller)继承了上一次的调度器(smart_controller),并且分解了之前的schduel方法,内容分布在run()和新建的类ELE_thread的isCarry()和run()里.在程序运行启动了类ELE_thread 的三个线程,分别代表三部电梯的控制系统,分别操作三部电梯. 度量分析: 问题都出在ELE_thread 的run()里,包括圈复杂度和嵌套深度.主要是因为把上一次的大部分代码都集中放

OO第二次博客

oo5_7 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,c

OO第二次博客作业

一.第五次作业--多线程电梯 (1)分析: 因为时间比较紧迫,所以采用了伪多线程的方式,即计算还是单线程,但是输出是三个多线程.不过最后被判无效了,GG. 现在分析一下觉得还是挺清晰的,电梯开三个线程,在分派任务的时候wait,notify一下就行了. 算法分析: 1.每个电梯有一个list队列,在新任务来的时候决定加入哪个list 2.有变动的list更新(用上一次的代码,从头算到尾,得到应该输出的真实时间) 3.三个线程死循环,遍历对应的list,如果有请求的应输出时间小于当前时间,输出,标

仿Expandablelistview效果的ListView(加入了子列表渐入渐出的动画)

新来的项目要求第一眼一看就是用Expandablelistview.效果图如下:             其实本来希望直接使用Expandablelistview的,但是需求Expandablelistview在展开一个group时有个动画效果--该group的child一个一个滑动出来并且把下面的group"挤"下去.本以为这个Expandablelistview组件肯定有相关方法的,但竟然没有!网上居然也查不到(有很多人问同样的问题,答案却都是:继承Expandablelistvi

Unity实现场景加载渐入渐出效果

项目中要用到加载场景的时候有个渐入渐出的效果,做了一下,跟大家分享 首先,创建两个场景Main和Game场景: 其次,在Main场景中创建FandeScene.cs脚本,创建Fade空对象,挂载,给一张黑色的图片,拖成预设体,同样也拖到Game场景中. using UnityEngine; using System.Collections; public class FadeScene : MonoBehaviour {     public Texture blackTexture;     

js原生实现div渐入渐出

jq对渐入渐出进行封装,简单的使用连个方法就可以实现.fadeIn(),fadeOut();如果我们界面没有使用jq那么原生怎么实现呢? 我们讲解一下,这个原理.当我们要实现渐入的时候,首先是让隐藏的div慢慢的显示,通过让opacity慢慢从 0.0 (完全透明)到 1.0(完全不透明).渐出就是逻辑反过来的. 下面我们直接贴代码: css: * {margin:0; padding:0} body {font:12px Verdana,Arial; color:#777; backgroun

弧形菜单2(动画渐入)Kotlin开发(附带java源码)

弧形菜单2(动画渐入+Kotlin开发) 前言:基于AndroidStudio的采用Kotlin语言开发的动画渐入的弧形菜单...... 效果: 开发环境:AndroidStudio2.2.1+gradle-2.14.1 涉及知识:1.自定义控件,2.事件分发等 部分代码: Activity: class HomepageActivity : AppCompatActivity() { private var homePageMenuLayout: HomePageMenuLayout? = n

Android深度探索HAL与驱动开发 第二章

Android深度探索HAL与驱动开发 第二章 搭建Android开发环境 读书笔记 一.Android底层开发需要的工具 1.JDK6或以上版本 2.Eclipse3.4或以上版本 3.ADT(用于开发Android的应用程序) 4.CDT(用于开发Android NDK程序) 5.Android SDK 6.Android NDK 7.交叉编译环境 8.Linux内核源代码 9.Android源代码 10.用于调试开发板的串口工具:minicom 二.安装JDK 下载JDK后在终端输入 #

你好,博客园!!第一弹~局域网下的简易聊天室,socket与多线程简结

发觉博客园里面关于这些基本知识点的详细内容真是应有尽有,所以这里的随笔就不再重复了,就积累一下简单的用法-- 1.Socket 最近学网络编程,也就是Socket,套接字,一个用来建立链接传输数据的工具. 数据传输发生在"客户端"与"服务端"之间,下面是一种建立连接传输数据的简单方法: (1)客户端 1 try{ 2 //服务端ip 3 String ip = "127.0.0.1"; 4 //服务器端口 5 int port = 5000; 6