OO第二单元总结
OO第二单元总结
目录
1.写在前面
经过这一段时间的学习(OO和OS都在学进程、线程),我对线程的了解程度也从只听说过这些词加深到了能熟练使用进程完成去多部个线程的协调调度。虽然我取得了不小的进步,但我也知道我目前所了解到的相对于真正的多线程设计来说只是沧海一粟,在OO整个单元结束之后还接着会通过其他方式对多线程进行更深的了解。
本单元有三次电梯作业。第一第二次都比较简单,不太会出问题。而第三次多线程电梯则是神玄学发生地(特别是对于各种奇怪的bug),交上去的程序多线程安全有没有保证谁也不知道。(特别是测评机还有那么一点神秘。)这些都对我进行程序的编写调试造成了一些困难,也迫使我更改自己的设计,采用更健壮(简单)的结构。菜是原罪啊
那么废话不多说,下面开始对自己的作业进行分析吧。
2.作业设计分析总结
2.1.傻瓜电梯(FIFO)
线程设计分析总结
怎么说呢。。。这次作业唯一需要的做两个的线程就是读入和读出,以及一部电梯。但是由于我想的比较多,于是就写的比较复杂QAQ
我开了两个线程,一个用于读入数据(Input),一个是电梯运行。为了方便之后的作业,我设计了一个调度类s,将Input和电梯联系起来。
电梯当前等待队列为空时,wait()。Input读入request时,notify。Input读入null时,先将null传入电梯,然后notify后break。这样不用暴力轮训避免cpu超时,也能使程序读入null后正常结束。后两次的作业也采用了同样的读入数据的方法。
基于度量的分析
uml类图:

复杂度:


注:
ev(G)为Essentail Complexity,表示一个方法的结构化程度
iv(G)为Design Complexity,表示一个方法和他所调用的其他方法的紧密程度
v(G)为循环复杂度
run方法的结构化复杂度较高是因为我将电梯的大部分操作包括开门关门都直接写在了里面~其实作为主要类才20行也不复杂呀
第一次电梯确实比较简单,无论是方法抑或是类的复杂度都没有问题~
2.2.小聪明电梯(ALS)
线程设计分析总结
我认为,第二次的作业难度并不在线程上,而是在电梯类调度的实现上。
由于害怕使用其他调度互测被爆,我最终还是使用了ALS(A LITTLE STUPID)调度。我也并没有加任何奇奇怪怪的类,因此依旧保持了第一次傻瓜电梯的类和方法,依旧是两个线程Input和Elevator。
第二次线程方面同第一次电梯一样~
基于度量的分析
uml类图:

复杂度:


注:
ev(G)为Essentail Complexity,表示一个方法的结构化程度
iv(G)为Design Complexity,表示一个方法和他所调用的其他方法的紧密程度
v(G)为循环复杂度
第二次电梯,为了实现ALS捎带,我在moveup和movedown两个方法中对于当前请求队列进行了遍历,来判断是否需要开门,因此这两个方法的结构复杂度和循环复杂度相比其他方法都比较高。至于Elevator.run() ,则是由于依赖他其对其他方法进行调用,因此结构负责度也会比较高。
2.3.多线程电梯(SS) 死锁电梯(并没有)
线程设计分析总结
这次电梯则是主要和线程相关啦~
本次作业原本的设计是使用一个input线程和3个Elevator线程,通过Dispatcher相连,从而完成输入和电梯调度。但是由于测评机在测评时对线程的Input.start()有一定延迟,在我某一次提交玄学发现一个输入都没读到后,便将input线程直接写进了main函数(即ElevatorSystem)。(其实本质上是一样的)
另外,由于拆分request时会造成request读入后阻塞下个request的读入,于是我把每个request进入dispatcher后,另开了一个线程(调用RequestPerformer),然后根据是否需要拆分将一个或两个request放入相应电梯。当request被拆分为两个firstRequest和secondRequest时,当其firstRequest送入后进行wait,等待其被电梯完成后发出notify信号,这时secondRequest再被送进其相应电梯,从而保证电梯的效率和正确性。
feedRequest(firReq, elevatorFir, firLock);
synchronized (firReq) {
try {
firReq.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
feedRequest(secReq, elevatorSec, secLock);
carried.remove(carRemove.get(i));
synchronized (carRemove.get(i)) {
try {
carRemove.get(i).notify();
} catch (Exception e) {
e.printStackTrace();
}
}
synchronized (elevatorLock) {
elevatorLock.notifyAll();
}
三个电梯各司其职,对第二次电梯进行复用,确保设计的简单性和可靠性。
基于度量的分析
uml类图:

行数统计:

复杂度:



注:
ev(G)为Essentail Complexity,表示一个方法的结构化程度
iv(G)为Design Complexity,表示一个方法和他所调用的其他方法的紧密程度
v(G)为循环复杂度
OCavg为平均循环复杂度
WMC为总循环复杂度
毫不意外的,电梯的moveup()/movedown()和run()方法再次复杂度飘红,而本次再开门时需要对拆分后的firstRequest进行notify操作,导致turnon的复杂度也上升。
各个类的复杂度中,以Elevator类、main(ElevatorSystem)类和RequestPerform类较高。这也很科学,由于电梯和RequestPerform类各完成了调度一半的工作,其类的复杂度因此较高。而由于我被迫将Input类合并到main类中,导致该类复杂度也出现了问题。
至于类之间的耦合程度,可以看出来还是相当正常的,这也表明由于设计结构合理,代码的可复用和可修改性都会得到提升。
3.基于Soild原则的评价
3.1SRP(Single Responsibility Principle):
程序Input、Elevator、main、Dispatcher和RequestPerform类等,各司其职。除了在第三次由于玄学问题导致需要将Input类的功能放到main中之外,能较好的符合单一功能原则。
3.2OCP(Open Close Principle):
开闭原则。不同于上一个单元的三次作业两次重构(因为第一次没法重构hhh),本单元作业我一次也没有重构过hh(因为大概能猜到之后会干啥)。而我在分配调度时为了增加功能,则是直接新创建了RequestPerformer类,完成分配调度,这也是我有关开闭原则做的好的地方。
3.3LSP(Liskov Substitution Principle, ISP(Interface Segregation Principle)and DIP(Dependency Inversion Principle):
说来惭愧,我这次作业没怎么使用接口和继承(这也是设计问题),因为各类的功能都不太一样,很难提取出共性(要非说都有run的话...确实都是extend Thread)。我看有些同学在第三次电梯中,共用Elevator抽象类,然后实例化ElevatorA、ElevatorB、ElevatorC。我倒是觉得这样会产生很多重复代码,违反Single Responsibility Principle,反而不够Soild。
我在本次作业的设计中,没有太多的使用接口和继承。不过我也学习了Soild原则评价。在之后的作业中,我会尽可能的多思考,满足这些原则。
4.BUG分析
4.1自己的BUG
我三次作业在强侧和互测中都没有出现正确性问题,因为我没做太多优化hhhh
笑着笑着看着强侧分哭了起来
那么,我说我这三次作业没有BUG你信吗?
反正我是信又不信的,因为在我使用本地测评机进行测评时,确实出现过一次不可复现的BUG,但也就仅仅出现过这一次。我至今没有办法确定BUG在我的程序中还是在我的(大佬给我的)测评机中。如果在我的程序中,那么可能是因为我在将Request传入电梯时需要开很多线程,可能开的太多了会产生冲突?(可是我锁了啊)
这么说我正确性没出现问题也是幸运的。
4.2别人的BUG
第一次和第三次都没有找到别人的BUG。(第一次确实没有,第三次就算有也不一定可复现)。
第二次作业中我倒是找到了两位同学的两个BUG。我是使用半自动的测评机,自己手输数据找到BUG的。他们的调度很奇怪(思路不同),我没仔细看,但是在特定数据下,一个会跑到0层,一个会跑到17层(这确实很奇怪。。。)
5.心得体会
之前一直听说电梯中怎么怎么魔鬼,自己闯下来后倒是觉得还好。不过这倒也不一定说是我学的好,也许只是我优化的不够多hhh。相比于前几届学长学姐们第二周就上电梯,第五周直接三部电梯一起爽,我们的课程结构显然合理亲民了。从发展的眼光看,这也是OO课程在逐渐进步,逐渐做的更好。
经过了这一单元的学习,我能明显感到我编程能力的进步。不只是java编程,由于互测环节的存在,我们也开始自己学习构造测评机。通过理解,构造测评机,让我能感受到脱离了ide后更加基本的编程原理。除了java的编译和测试,我也在构造测评机的过程中对bat、shell等脚本语言有了更实用的了解。这也是面向对象课程给我带来的进步,也许不仅仅是学习面向对象思想,而是借这个机会让自己能更好的重新系统学习程序设计、构造和测试。
最后,感谢老师和助教们的付出。想必维护测评网站,写测评机确实有那么点麻烦hhh

浙公网安备 33010602011771号