一、设计策略分析总结
第二单元的三次作业总的来说都是生产者消费者模型,从一对一的傻瓜电梯到采用捎带策略的傻瓜电梯到多电梯协作的电梯系统,问题逐渐变得复杂,但是解决策略都是相同的。第一步:将请求放入调度器的总请求队列中,第二步:各个电梯采用各自的调度算法从主请求队列中取走请求并加入各自的任务队列(在电梯中的乘客)中,第三步:乘客送达目的地,将请求从各自的任务队列中移除。
1.1第一次电梯作业:
第一次电梯作业是一对一的傻瓜电梯,总体结构比较简单,一共有四个类,主类主要负责开启线程,电梯类负责读取请求,决定电梯的方向,显示电梯的状态。乘客类负责接收请求并放入调度器的主请求中。调度器类负责维护一个主请求队列。一共有三个线程,主线程,乘客线程,和电梯线程。乘客线程和电梯线程共享主请求队列。
1.2第二次电梯作业:
第二次电梯作业在第一次电梯作业基础上多了捎带算法,我采用的方法是扩展调度器的功能,在调度器中加入电梯的任务队列(存放电梯中的乘客),并设计出主请求进入任务队列的调度算法,即扫描主请求,该楼层可捎带时则将请求加入任务队列。其余各类都没有较大的改变。
1.3第三次电梯作业:
第三次电梯作业在第二次电梯作业基础上变成了多电梯,并且各个电梯停留楼层不同,说明存在转搭的情况,事情变得复杂多了。主要的扩展核心还是调度器类,首先我将每个乘客的属性进行了扩展,附加了elva,fromfloor2,tofloor2和elva2四个属性,收到请求时,我根据调度算法,将请求分为两个子请求(需要转搭的情况),将第一个请求进入楼层,到达楼层,所用电梯分别放入fromfloor,tofloor,elva,将第二个请求进入楼层,到达楼层,所用电梯分别放入fromfloor2,tofloor2,elva2。这样各个电梯在选择请求时,就会先观察elva属性,与自己电梯编号相同的请求才会放入自己的任务队列中。
关于转搭的算法,我采用的是优先A电梯,然后是B电梯,最后选择C电梯(根据时间长短)。第三次电梯作业一共有七个类,主类,调度器类,三个电梯类,一个乘客类,一个扩展的请求类。一共有五个线程,主线程,乘客线程和三个电梯线程。
二、基于度量的程序结构分析
(一)第一次电梯作业
1.类图
2、UML协作图
3、方法度量
4、类度量
(二)第二次电梯作业
1.类图
2、UML协作图
3、方法度量
4、类度量
(三)第三次电梯作业
1.类图
2、UML协作图
3、方法度量
Method |
ev(G) |
iv(G) |
v(G) |
com.oocourse.elevator3.Elevator.Elevator(Tray) |
1 |
1 |
1 |
com.oocourse.elevator3.Elevator.run() |
3 |
7 |
19 |
com.oocourse.elevator3.Elevator2.Elevator2(Tray) |
1 |
1 |
1 |
com.oocourse.elevator3.Elevator2.run() |
3 |
7 |
19 |
com.oocourse.elevator3.Elevator3.Elevator3(Tray) |
1 |
1 |
1 |
com.oocourse.elevator3.Elevator3.run() |
3 |
7 |
19 |
com.oocourse.elevator3.PersonRequest2.getFromFloor() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.getFromFloor2() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.getPersonId() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.getToFloor() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.getToFloor2() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.gete() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.gete2() |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.sete(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.sete2(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.setf(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.setf2(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.setid(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.sett(int) |
1 |
1 |
1 |
com.oocourse.elevator3.PersonRequest2.sett2(int) |
1 |
1 |
1 |
com.oocourse.elevator3.Producer.Producer(Tray) |
1 |
1 |
1 |
com.oocourse.elevator3.Producer.run() |
3 |
3 |
3 |
com.oocourse.elevator3.Test.main(String[]) |
1 |
1 |
1 |
com.oocourse.elevator3.Tray.Tray() |
1 |
1 |
1 |
com.oocourse.elevator3.Tray.direction(PersonRequest2,int) |
2 |
4 |
5 |
com.oocourse.elevator3.Tray.firsti(int) |
3 |
2 |
3 |
com.oocourse.elevator3.Tray.get1(int,int) |
4 |
12 |
14 |
com.oocourse.elevator3.Tray.get2(int,int) |
4 |
12 |
14 |
com.oocourse.elevator3.Tray.get21(int,int) |
1 |
4 |
4 |
com.oocourse.elevator3.Tray.get22(int,int) |
1 |
4 |
4 |
com.oocourse.elevator3.Tray.get23(int,int) |
1 |
4 |
4 |
com.oocourse.elevator3.Tray.get3(int,int) |
4 |
12 |
14 |
com.oocourse.elevator3.Tray.getsymble() |
1 |
1 |
1 |
com.oocourse.elevator3.Tray.isEmpty() |
1 |
4 |
4 |
com.oocourse.elevator3.Tray.isopen1(int,int) |
11 |
14 |
18 |
com.oocourse.elevator3.Tray.isopen2(int,int) |
11 |
14 |
18 |
com.oocourse.elevator3.Tray.isopen3(int,int) |
11 |
14 |
18 |
com.oocourse.elevator3.Tray.put(PersonRequest) |
1 |
4 |
5 |
com.oocourse.elevator3.Tray.putsymble() |
1 |
1 |
1 |
com.oocourse.elevator3.Tray.shunda(int,int,int) |
3 |
5 |
6 |
com.oocourse.elevator3.Tray.trans(PersonRequest2) |
1 |
2 |
2 |
com.oocourse.elevator3.Tray.transA(PersonRequest) |
1 |
5 |
7 |
com.oocourse.elevator3.Tray.transB(PersonRequest) |
1 |
5 |
5 |
com.oocourse.elevator3.Tray.transC(PersonRequest) |
1 |
5 |
10 |
4、类度量
Class |
OCavg |
WMC |
|
com.oocourse.elevator3.Elevator |
7 |
14 |
|
com.oocourse.elevator3.Elevator2 |
7 |
14 |
|
com.oocourse.elevator3.Elevator3 |
7 |
14 |
|
com.oocourse.elevator3.PersonRequest2 |
1 |
14 |
|
com.oocourse.elevator3.Producer |
2 |
4 |
|
com.oocourse.elevator3.Test |
1 |
1 |
|
com.oocourse.elevator3.Tray |
5.43 |
114 |
|
|
|
|
三、BUG分析
三次作业强测中我的程序都没有出现BUG,但是整体性能却比较糟糕,第二次电梯作业只有83.3的强测分,原因可能有两个,第一个是寻找第一位乘客时,我按照先来先上原则,这一步可能有较大优化空间,即先来先上并不优秀,而且期间可以捎带而我没有捎带。第二个原因可能是捎带策略本身性能并不优秀。
第三次电梯作业我依然是全对,但是得分只有85.8,优化部分做得很差,最主要的原因是,我发现A电梯满人之后,那些既可以上A电梯又可以上B电梯的乘客只会等待A电梯,不会自动的上B电梯。这个情况完全是我的调度算法的问题,导致了性能的低下。
四、心得体会
我觉得这次作业对初学者来说真的是十分友好,我是第一次写多线程程序,本来第一次应该会比较难上手,但是傻瓜电梯是真的很好上手,我在网上找了找生产者消费者程序的例子,并且结合ppt上的例题,照着照着就写出来了,第一次体会到了多线程程序的结构是多么的清晰。紧接着第二次作业让我熟悉了调度器的作用,第三次作业则是更贴近现实的情景,在仅有的三次训练中,多线程该踩的坑我踩过了,多线程的各种方法早已铭记于心。