OO第二次博客作业

一. 基于度量分析程序结构

1.1 第一次作业

问题概述: 完成的任务为单部多线程傻瓜调度(FAFS)电梯的模拟

多线程设计策略:

 

 

1.1.1 类图

 

 此次作业算是第一次接触多线程,然而第一次作业整体的实验目标比较简单,因此我对此次实验的设计更像是单线程。由上述类图可知,在此次实验中一共有两个线程,一个是输入端,另一个则是电梯端。其中的scheduler类并非是一个线程,主要负责接受输入端的请求以及给电梯提供相应的请求。由于两个线程共享一个请求队列资源,因此运用了synchronize方法来实现同步控制。

1.1.2 复杂度分析

 

 

 由上述复杂度矩阵可知,第一次的单部多线程电梯设计确实比较简单,代码复杂度也相对较低。

1.1.3优缺点分析

 此次作业其实算不上很好的设计,但由于没有性能分而且电梯策略也很简单所以基本没有失分。现在回顾当时的设计思路我觉得优点在于运用了较为合适的方法使得两个线程避免了因为竞争同一资源而出现的不同步现象;然而缺点则是没有进行更深层次的思考,比如应该多想想如何进行优化,以及synchronize方法是否为最优的同步实现方法。

 

1.2 第二次作业

问题概述:完成的任务为单部多线程可捎带调度(ALS)电梯的模拟

设计策略:(第二次作业实在是设计得太差,感觉也没有参考价值就没有将设计策略放上来,下面的类图可以很好地说明第二次作业真的是三次作业中最为不清晰的一次)

 

1.2.1 类图

 这次作业总结来讲做得真的很不好,按道理来说第二次电梯作业和第一次的差别并不大,同样是单部电梯的多线程调度,只是这次加上了调度, 然而我在基于第一作业的基础上写完第一版后想要尝试一下其他的上锁策略,而不仅仅是运用之前常用的synchronize,然后就有了上述异常复杂而诡异的程序设计。单看类图就可以看出来这次作业设计上真的存在很大的问题,类图复杂且冗余,按道理来讲本没必要加一个RequestQueue类,sheduler和elevator之间存在的lock锁也很奇怪。在进行此次作业总结时候的最大感受便是应该在每次设计完程序后就看看类图架构的,这样也好及时发现问题进而避免不必要的麻烦。

 

1.2.2 复杂度分析

 

这次代码的复杂度真的是让人难以启齿,代码复杂且代码量高,方法的重用复杂度也偏高,感觉这次的作业可以作为之后做作业过程中的警示吧。

 

1.2.3 优缺点分析

 优点:这次作业真的没有很多优点,在第二部分的bug分析中也可以看到复杂而冗余的设计一定不会带来好的效果,尽管可以勉强过中测,但是在强测阶段一定是会出现问题的,希望自己能好好记住这次作业带来的教训吧。

缺点:缺点在复杂度分析以及类图分析中已经提到了一部分,设计上不合理,没有仔细思考或者混乱思考了线程之间的关系,没有很好地运用老师上课所讲的单例模式,对于线程的同步以及线程之间的通讯也理解得不透彻。

 

1.3 第三次作业

问题概述:完成的任务为多部多线程智能(SS)调度电梯的模拟。

设计策略:

 

 由上图可看出第三次作业的设计和第一次作业很像,不同之处主要在于第三次作业有三个电梯线程,因此在Scheduler类也增加了一个相应的判断当前电梯是否为最优选择的方法,同时为了准确地将换乘乘客顺利运送到目的地,我采用的方法是将这样的request进行拆分,并找到换乘的中间楼层,在前半段request执行完后再执行第二段,总的来讲第三次作业进行调度以及决策的都是scheduler,elevator只需要发出请求然后分别进行各自的运行。

1.3.1 类图

 

有了第二次作业的教训,第三次作业我进行了重构,也理清了线程之间的关系,从以上类图可以看出,此次设计就没有第二次那样诡异了, 比较常规也较为简单,虽然为多部电梯的调度,但是电梯总归来讲都是一个类,然后调度器作为电梯和输入的共享部分。也不能说这次作业就很好,但至少从类图的角度分析还是比较清晰明了的。

1.3.2 复杂度分析

 

 此次作业的复杂度相较于之前一次要好一点,虽然个别方法的复杂度较高,但是总体平均后的复杂度还算可以,至少说明代码的耦合程度不算太低。

1.3.3 优缺点分析

 优点:此次作业较大的好处是设计简单,尽管多电梯看起来比单电梯复杂,但只要想清楚该怎么设计,如找到竞争资源,运用单例模式,运用合适的方法实现线程调度和同步,以及实现线程之间的合理通信就能够较为科学得解决此次问题。

缺点:这次作业因为有了上次作业盲目优化带来的教训,在此次作业里几乎没有实现很特别的优化。在正确完成线程调度的基础上,所有的优化仅仅为每个电梯内部的捎带,这也导致了尽管测试通过,但是几乎没有拿到性能分的情况。

  


 

 二. 分析程序问题以及问题原因分析

 

 

 


 

 

三. 发现问题的策略


1.在自己做作业的过程中,发现问题的策略为:

(1)运用debug加入断电调试,虽然debug模式对于多线程问题的问题浮现并没有任何帮助,但是我一开始是通过对每个线程的入口加断点的方式来帮助自己理解各个线程之间的调度,加深了线程之间运行互不干扰的印象,这个调试也算是帮助自己巩固知识吧。另外我在第二次作业的中遇到CPU_TIME_EXCEPT的问题,因为最开始我的设计是电梯不断轮询调度器,但因为第二次作业本身的设计有问题所以就出现了多个线程同时运行的情况,在经过讨论区同学的提示后,我才用了wait等方法来避免某一线程空跑的情况,为了检验自己设计是否正确,可以打开debug单步调试查看各个线程取锁放锁的状态。

(2)从发现程序本身的问题来讲,主要还是运用写测试用例的方法来发现问题。测试用例一般是我在写完程序后会再次回顾指导书,找出关键以及自己能想到的可能会出现坑的地方,写一点测试样例来进行找错。当然这个方法也有一点局限性,有时候自己的惯性思维会让一些隐藏的bug仍然没办法测出来。

(3)逛讨论区运用其他同学提出的较优方案。讨论区中不少同学都提出了一些共性问题,下面的回答有参考价值的都会拿来帮助自己发现bug。

 

 


 四. 设计模式分析

  • 单例模式:某个类只能有一个实例,提供一个全局的访问点。

    在此次设计中,scheduler类只有一个实例,在最开始的创建,input可以通过putReq方法来向scheduler中的请求队列添加新请求,电梯类则可以调用takeReq方法来从scheduler中获取请求。

  • 简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

    在此次设计尤其是第三次作业中,scheduler通过传入的载客限制,可停留楼层等决定到底创建哪一个电梯实例。

  • 生产者消费者模式:在多线程中,生产者消费者模式是最常见的设计模式

    在此次作业中,input为生产者,elevator则是消费者,共享对象为scheduler中的请求队列。

 


 

五. 心得体会

  1. 这一部分的问题其实现在回想起来真的不算很难,只要能准确理解多线程之间的交互,抛开优化不讲,实现正确还是不难的。而且在课上一定要认真听讲,老师当堂课讲得内容往往是接下来作业中的切入点。

   2. 不要过度追求优化导致不必要的失分,尽管每次指导书末尾助教都会有这样的温馨提示,然而真真明白这个道理还是在自己真实感受之后。优化一定是基于当前已有设计的进一步提升,而不应该一开始就把优化当做重点来进行设计,这样真的只会得不偿失。

   3.在之后的作业中,尽量记得查看一下类图,有时候图形化的界面会比较直观地让人体会到设计的优劣。

 

  

posted on 2019-04-22 20:56  Delia-Y 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/xinyiyu/p/10733076.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值