BUAAOO 第二单元作业总结

BUAAOO 第二单元作业总结

单元综述

单元总共为三次作业,难度递增。

  • 第一次:完成的任务为单部多线程傻瓜调度(FAFS)电梯的模拟。

  • 第二次:需要完成的任务为单部多线程可捎带调度(ALS)电梯的模拟。

  • 第三次:需要完成的任务为多部多线程智能(SS)调度电梯的模拟。

通过这三次作业,我逐渐完成了一个多线程电梯系统,对于线程也有了更深的理解。

 

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

本文中基于度量分析的图片采用IDEA的Metrics生成。

分析结果解释的方法来源于博客(https://www.cnblogs.com/qianmianyu/p/8698557.html

  • ev(G):即Essentail Complexity,用来表示一个方法的结构化程度,范围在之间,值越大则程序的结构越“病态”,其计算过程和图的“缩点”有关。

  • iv(G):即Design Complexity,用来表示一个方法和他所调用的其他方法的紧密程度,范围也在之间,值越大联系越紧密。

  • v(G):即循环复杂度,可以理解为穷尽程序流程每一条路径所需要的试验次数。

对于类,有OCavgWMC两个项目,分别代表类的方法的平均循环复杂度和总循环复杂度。

 

第一次作业

类图

复杂度分析表

Method ev(G) iv(G) v(G)
Elevator.Elevator(RequestList,int) 1 1 1
Elevator.close(int) 1 1 1
Elevator.in(int,int) 1 1 1
Elevator.open(int) 1 1 1
Elevator.out(int,int) 1 1 1
Elevator.run() 1 2 2
Elevator.sleep(int) 1 2 2
Input.Input(RequestList) 1 1 1
Input.run() 3 3 4
Main.main(String[]) 1 1 1
Request.Request(PersonRequest) 1 1 1
Request.Request(int,int,int) 1 1 1
Request.getFromFloor() 1 1 1
Request.getPersonId() 1 1 1
Request.getToFloor() 1 1 1
RequestList.get() 1 2 3
RequestList.getFirst() 1 1 1
RequestList.getSize() 1 1 1
RequestList.put(Request) 1 2 3
Class OCavg WMC
Elevator 1.14 8
Input 2 4
Main 1 1
Request 1 5
RequestList 1.5 6

分析

在第一次作业中,我有两个仓库,分别是insideList(List中是电梯里面的请求),outsideList(List中是电梯外面,即还没有被电梯取走的请求)。Input线程向仓库outsideList里里面放东西,Elevator从仓库outsideList里面取东西。Elevator将从outsideList中取出来的指令放到自己的insideList里,指令执行完毕(即人从电梯中出去之后)将指令从insideList中取出。

第一次调度方法我直接采用的傻瓜调度,将指令一个一个执行。每一个Method的复杂度都不是很高,整体架构还可以。

 

第二次作业

类图

复杂度分析表

Method ev(G) iv(G) v(G)
Elevator.Elevator(InsideList,OutsideList,int) 1 1 1
Elevator.arrive(int) 1 1 1
Elevator.close(int) 1 1 1
Elevator.getDir(int,int) 2 1 2
Elevator.getFloorNow() 1 1 1
Elevator.getNextDir(Request) 7 10 10
Elevator.in(int,int) 1 1 1
Elevator.middle(int,int) 1 11 13
Elevator.open(int) 1 1 1
Elevator.out(int,int) 1 1 1
Elevator.printBeside() 1 7 7
Elevator.printIn(Request) 1 2 2
Elevator.printOut(Request) 1 2 2
Elevator.run() 1 6 6
Elevator.sleep(int) 1 2 2
Input.Input(OutsideList) 1 1 1
Input.run() 3 3 4
InsideList.get(int) 1 3 4
InsideList.getEle(int) 1 1 1
InsideList.getOutPeople(int) 3 2 3
InsideList.getSize() 1 1 1
InsideList.isEmpty() 2 1 2
InsideList.put(Request) 1 2 3
Main.main(String[]) 1 1 1
OutsideList.get(int) 2 3 4
OutsideList.getDownPick(int) 3 2 4
OutsideList.getEle(int) 1 1 1
OutsideList.getSize() 1 1 1
OutsideList.getUpPick(int) 3 2 4
OutsideList.isEmpty() 2 1 2
OutsideList.put(Request) 1 2 3
Request.Request(PersonRequest) 1 1 2
Request.Request(int,int,int) 1 1 1
Request.getDir() 1 1 1
Request.getFromFloor() 1 1 1
Request.getPersonId() 1 1 1
Request.getToFloor() 1 1 1

 

Class OCavg WMC
Elevator 3 45
Input 2 4
InsideList 1.83 11
Main 1 1
OutsideList 2 14
Request 1.17 7

分析

这次我还是沿用了第一次作业的思路,设置了insideList和outsideList两个仓库。整体采用ALS的想法,并且在电梯运行中间加入了捎带人的操作。

这次Elevator.middle(int,int) 和 Elevator.getNextDir(Request) 的循环复杂度和设计复杂度较高。这两个方法一个是处理接人的问题,一个是处理电梯下一个运行方向的问题。因此执行次数可能比较多。

 

第三次作业

类图

  • 整体

  • package : elevator

  • package : input

  • package : requestList

复杂度分析表

Method ev(G) iv(G) v(G)
Main.main(String[]) 1 1 1
elevator.Elevator.Elevator(InsideList,OutsideList,FinalList,int,int[],int,char,int,int) 1 2 2
elevator.Elevator.arrive(int) 1 1 1
elevator.Elevator.close(int) 1 1 1
elevator.Elevator.getDir(int,int) 2 1 2
elevator.Elevator.getOutSize() 1 1 1
elevator.Elevator.in(int,int) 1 1 1
elevator.Elevator.insideOut(Request) 1 2 2
elevator.Elevator.middle() 1 3 3
elevator.Elevator.middleDown() 3 12 15
elevator.Elevator.middleUp() 3 12 15
elevator.Elevator.open(int) 1 1 1
elevator.Elevator.out(int,int) 1 1 1
elevator.Elevator.printBeside() 1 17 19
elevator.Elevator.printIn(Request) 1 1 1
elevator.Elevator.printOut() 1 1 1
elevator.Elevator.run() 1 8 8
elevator.Elevator.sleep(int) 1 2 2
input.Input.Input(OutsideList,FinalList) 1 1 1
input.Input.run() 3 3 4
requestlist.FinalList.get(Request) 2 3 4
requestlist.FinalList.getIndex(Request) 3 2 3
requestlist.FinalList.put(Request) 1 2 3
requestlist.FinalList.size() 1 1 1
requestlist.FinalList.waiting(Request) 1 3 4
requestlist.InsideList.get(int) 1 3 4
requestlist.InsideList.getEle(int) 1 1 1
requestlist.InsideList.getFirstIndex(char) 3 2 3
requestlist.InsideList.getNotRemove() 2 2 3
requestlist.InsideList.getOutPeople(int) 3 2 3
requestlist.InsideList.getSize() 1 1 1
requestlist.InsideList.haveDown() 1 2 3
requestlist.InsideList.haveOut(int) 3 2 3
requestlist.InsideList.haveUp() 1 2 3
requestlist.InsideList.isEmpty() 2 1 2
requestlist.InsideList.put(Request) 1 2 3
requestlist.OutsideList.get(int) 1 1 1
requestlist.OutsideList.get(int,char) 2 3 4
requestlist.OutsideList.getDownPick(int,char) 3 4 5
requestlist.OutsideList.getEle(int) 1 1 1
requestlist.OutsideList.getFirstIndex(char) 3 2 3
requestlist.OutsideList.getNotRemove(char) 2 3 4
requestlist.OutsideList.getSize(char) 1 2 3
requestlist.OutsideList.getUpPick(int,char) 3 4 5
requestlist.OutsideList.isEmpty() 2 1 2
requestlist.OutsideList.peopleAbove(int,char) 1 4 5
requestlist.OutsideList.peopleBelow(int,char) 1 4 5
requestlist.OutsideList.printId() 1 2 2
requestlist.OutsideList.put(Request) 1 7 8
requestlist.OutsideList.size() 1 1 1
requestlist.Request.Request(PersonRequest) 1 1 3
requestlist.Request.Request(int,int,int,char) 1 1 1
requestlist.Request.getDir() 1 1 1
requestlist.Request.getDirect() 1 1 1
requestlist.Request.getFromFloor() 1 1 1
requestlist.Request.getPersonId() 1 1 1
requestlist.Request.getToFloor() 1 1 1
requestlist.Request.getType() 1 1 1
requestlist.Request.getType2() 1 1 1
requestlist.Request.judgeDirect(int,int,int) 1 7 36
requestlist.Request.reManager() 2 5 10
requestlist.Request.transfer() 1 1 1
requestlist.Request.twoDirect() 1 1 1

 

Class OCavg WMC
Main 1 1
elevator.Elevator 2.88 49
input.Input 2 4
requestlist.FinalList 2 10
requestlist.InsideList 2.27 25
requestlist.OutsideList 2.29 32
requestlist.Request 2.31 30

分析

第三次作业中我的电梯沿用了之前的思想,不过由于是多电梯,总体设置了一个outsideList作为总请求仓库,每个电梯都分别设置了insideList作为电梯内部的请求仓库。

我的电梯总体采用的是Look算法,根据具体情况加了一些改动。我的电梯采用的是自己抢人的模式,即电梯在运行途中发现可以捎带的人,就把请求从outsideList 中取出放入自己的insideList中。先对指令进行处理,限定人可以乘坐的一个或几个电梯,之后就是电梯自由抢,哪个电梯先到就让人上哪个电梯。

这次的 eV(G)还都比较正常,不过有些方法的 iV(G)比较高。

 

二. 分析自己程序的bug

第一次作业

第一次作业,大概由于写的算法比较简单,而且之前测试的也比较充分,并没有出现什么bug。

 

第二次作业

第二次作业中,我也没有出现bug。

 

第三次作业

第三次作业中,我的程序出现了REAL_TIME_LIMIT_EXCEED的错误。我的电梯没有结束是因为我的电梯无法正确处理三层到1-15层的非直达现象。我当时分了三部分考虑换乘,在中间的这一部分中,我只考虑了三层到2,4层和2,4层到三层的换乘行为,没有考虑其他层。由于无法处理,就没有办法把这一项从outsideList里取出,导致了程序无法正确结束的情况。而且我的程序在Ctrl D输入较晚时可能会产生超时现象,因为在中间的时候没有考虑没输入结束符但outsideList已经为空的情况。

这次的错误可以说完全是因为自己测试不够充分造成的,起始这个错误在随机多数据输入的时候就会出现,下次一定应该注意测试的充分性。

 

三. 互测DEBUG

在每一次作业的互测中,我的样例主要来源于两个方面。一是来源于我自己在编程序的过程中没有想到的点,也就是在debug过程中发现的问题。二是来源于在互测过程中构造的样例

样例的构造

在前两次作业中,我有许多互测用例的构造都基于对于特殊情况的处理。比如电梯需要改方向时能否正确处理,以及开门时可以多人上下的情况处理

最后一次作业中,除了用上一次的用例,我还进行了对于换乘情况的测试。另外,我也构造了一些随机数据,测试电梯对于多条多种指令的情况能否正常运行。

 

四. Applying Creational Pattern

在课上老师的讲解过程中,我知道了调度器的妙用。我在这三次作业中都没有用到调度器,感觉可能在可扩展性方面会稍微弱一些,如果需要改调度方法就需要在电梯类中直接进行修改。我觉得下次如果有机会,我觉得可以尝试调度器模式。

而且在我在每次捎带人的时候,都需要对List中的请求进行遍历,课上有讲过一种方法,给每个电梯直接构造一个接人表,我感觉这样可能会更加清楚一些。

 

五. 总结

在这一单元中,从刚开始对于多线程一知半解,到后来可以写出多电梯,在这一过程中,我对于多线程有了更加深刻了理解。我也要吸取最后一次的教训,还是要更加仔细的测试自己的代码,争取在下课单元中能有所进步吧。

猜你喜欢

转载自www.cnblogs.com/ydch-001/p/10753549.html