Lab6 猴子过河模拟器总结

Lab6总结

ADT设计方案

Monkey:代表一个猴子。有名字、方向和速度三个属性。只有几个Obsevers方法。
Rung:代表一个踏板。只有一个序号属性。
Ladder:代表一个梯子。有序号、踏板列表和猴子位置三个属性。有以下几个方法:

  1. hasMonkey:检查当前梯子是否有猴子。
  2. hasSameDirectionMonkey:检查当前梯子是否有同向的猴子。
  3. addMonkey:在猴子位置的映射中根据参数添加一组键值对。
  4. removeMonkey:在猴子位置的映射中删除一组键值对。
  5. Obesevers。
    MonkeyGenerator:代表一个猴子生成器。有一个最大速度属性。只有一个随机生成猴子的方法。
    MonkeyThread:代表一个猴子线程,继承于Thread。有猴子、梯子列表、梯子和踏板四个属性,其中梯子、踏板表示猴子当前所处的位置。其中重写了父类Thread的run方法:执行猴子选择梯子、上踏板、行进并到达重点的全部行为。
    RiverSimulator:主程序,代表猴子过河模拟器。首先根据配置文件读入参数,并根据猴子生成器定时产生一定数量的猴子。

梯子选择的策略方案

这里采用了strategy pattern,暂设计了两个策略。

ExclusiveStrategy:优先选择没有猴子的梯子,若所有梯子上都有猴子,则在岸边等待,直到某个梯子空闲出来。
实现如下:

  1. 遍历所有梯子
  2. 如果当前梯子没有猴子,将当前猴子放置到梯子上并行进到相应踏板上。
  3. 日志记录猴子选择梯子、踏板过程。
  4. 返回根据梯子、踏板算出的一个hash码,以便外部解析出梯子、踏板编号。
  5. 如果没找到相应梯子,返回-1。
    在这里插入图片描述
    SharingStrategy:优先选择没有猴子的梯子,若所有梯子上都有猴子,则优先选择没有与我对向而行的猴子的梯子;若满足该条件的梯子有很多,则随机选择。
    实现如下:
  6. 遍历所有梯子
  7. 如果当前梯子的猴子与给定猴子同向且当前梯子的猴子不位于第一个踏板上,将给定猴子放到这个梯子上,行进相应的步数
  8. 日志记录猴子选择梯子、踏板过程
  9. 返回根据梯子、踏板算出的一个hash码,以便外部解析出梯子、踏板编号。
  10. 没找到相应梯子返回-1
    在这里插入图片描述

猴子生成器

猴子生成器设计如下:
在这里插入图片描述
generateMonkey方法随机产生一个猴子。具体实现每t秒产生k个猴子的实现在RiverSimulator中:
在这里插入图片描述
根据配置参数,产生k个猴子并开始过河(即start猴子线程)后调用sleep方法使主线程停止t秒,之后继续产生,对于最后的N%k个猴子:
在这里插入图片描述

如何确保threadsafe?

监视器模式:设计Ladder这个ADT时采用了监视器模式,即为每一个方法添加synchronized关键字,保证一个线程在对一个梯子修改时其他线程不会访问这个梯子。

采用不可变的数据结构:大部分应用的数据结构都是不可变的。对于少数可变的数据结构,采用以下两种方法:

  1. 防御式拷贝:对于一个Obeservers,防御式拷贝保证了其不可变。例如:
    在这里插入图片描述
    在这里插入图片描述
  2. 构造独有方法进行数据结构的可变操作,例如:
    在这里插入图片描述
    外部只能通过这两个方法修改position。

锁:在猴子选定某一踏板后,将该踏板锁住,直到猴子离开这个踏板。这使得其他猴子此时不可以跳到这个踏板上,保证了线程安全。
在这里插入图片描述

系统吞吐率和公平性的度量方案

该部分均基于以下参数:梯子数量n=5、踏板数量h=20、猴子生成器的时间间隔t=3、猴子总数N=100、每次生成猴子数k=10、最大速度mv=10

吞吐率:

设计了一个TimeCombine的ADT,存储了每个线程的起始时间、终止时间和猴子上梯子的时间。
遍历所有TimeCombine,找到最大终止时间和最小起始时间,作差值得到所有线程运行时间。
考虑到程序运行时间不宜过长,这里将线程sleep的时间缩短至20ms,得到的时间乘(1000/20)还原为原时间。计算如下:
吞吐率 = 猴子总数totalNum / ((end - start) * 50 ms) =
totalNum * 20 / (end - start),即代码中:

误差分析:在缩短时间的时候会引入误差。因为线程本身运行是有额外时间开销的,因此实际运行时间是20ms+运行时间,扩大五十倍后使得原本可以小到忽略不计的运行时间放大,因此实际时间比理论时间要长,得到的吞吐率比理论要低。
时间间隔是20ms时,得到的吞吐率约为0.8左右:

将时间间隔提高到200ms,得到的实际吞吐率约为2.3左右:
按照先前的理论,随着间隔时间增大,运行时间相对较小,得到的吞吐率自然会提升,实验结果与理论符合得很好。

公平性:

根据公平性的公式,程序中设计为两层循环遍历所有的timeCombine,将观察两个start和两个moment的差值是否同号,同号的话统计公平性的计数器fair++;否则fair–。最终得到的fair是两次叠加的结果,即既包括F(A,B),也包括F(B,A)。因此将得到的fair除以2,再除以 ,即fair / (2 * N * (N - 1)/2) = fair / (N * (N - 1))
公平性有较大的随机性,不过间隔时间加长使得先出生的猴子更有可能比后出生的猴子踏上梯子,因此理论上讲,同一间隔时间可能会出现些许变化,而平均来说,间隔时间越长,公平性越高。
在时间间隔为20ms时得到的公平性:

三次测试得到的平均公平性约为0.3左右;
在时间间隔为200ms时得到的公平性:

三次测试得到的平均公平性约为0.6左右。
综上,公平性的测试结果也与理论符合得很好。

输出方案设计

日志
采用的是log4j,jar包在lib文件夹中。
日志内容输出到log.log文件中,在以下几种情况会输出日志:

  1. 猴子登上梯子
  2. 猴子等待
  3. 猴子行进
  4. 猴子到达对岸
    得到的日志文件如下图:
    在这里插入图片描述
    GUI
    应用到策略模式,因此GUI面板上有两个选项:独占策略和共享策略,即在岸边等待直至空闲梯子的策略和选择空闲梯子或有同向猴子的梯子。
    如下图所示:
    在这里插入图片描述

猴子过河模拟器v1

参数如何初始化

按照实验指导说明书中推荐的配置文件方案,创建了configuration.txt,内容如下:
在这里插入图片描述
主程序RiverSimulator读入该文件,根据正则表达式解析并初始化各参数。具体实现见RiverSimulator中的readFile方法。

使用Strategy模式为每只猴子选择决策策略

定义策略接口DecisionStrategy,如下:
在这里插入图片描述
返回值可以按照如下方式解析出所在的梯子和踏板:
在这里插入图片描述
在实例化MonkeyThread对象时将相应策略作为参数传入,以实现猴子以不同策略选择梯子:在这里插入图片描述

猴子过河模拟器v2

在不同参数设置和不同“梯子选择”模式下的“吞吐率”和“公平性”实验结果及其对比分析。

对比分析:固定其他参数,选择不同的决策策略

该部分均基于以下参数:梯子数量n=5、踏板数量h=20、猴子生成器的时间间隔t=3、猴子总数N=100、每次生成猴子数k=10、最大速度mv=10。同样地,这部分采用时间间隔20ms(具体见3.6),得到的吞吐率会偏小。

分别采用两种策略各得到三组数值,如下图:
在这里插入图片描述
在这里插入图片描述
可见,共享策略比独占策略有更高的吞吐率和更好的公平性。

对比分析:变化某个参数,固定其他参数

保持其他参数不变,变化n分别为1、2、3、4、5。得到如下两个图:
在这里插入图片描述
下图是公平性,做表格的时候忘改了。在这里插入图片描述

保持其他参数不变,变化t分别为1、2、3、4、5。得到如下两图:
在这里插入图片描述
下面也是公平性。
在这里插入图片描述

保持其他参数不变,变化N分别为10、100、1000。得到如下两图:
在这里插入图片描述
在这里插入图片描述

保持其他参数不变,变化k分别为1、10、50。得到如下两图:
在这里插入图片描述
在这里插入图片描述

保持其他参数不变,变化mv分别为5、6、7、8、9、10。得到如下两图:
在这里插入图片描述

分析:吞吐率是否与各参数/决策策略有相关性?

可以看到,吞吐率与决策策略有很大的相关性,共享策略比独占策略明显要高。
吞吐率也与n、mv参数相关。显然,梯子个数越多,同一时刻在梯子上的猴子往往越多,吞吐率越高;最大速度越大,猴子平均速度越高,通过梯子的时间越短,吞吐率越高。实验结果与理论吻合得很好。

压力测试结果与分析

略。

猴子过河模拟器v3

针对教师提供的三个文本文件,分别进行多次模拟,记录模拟结果。
吞吐率 公平性
Competiton_1.txt
第1次模拟 1.411 0.927
第2次模拟 0.888 0.917
第3次模拟 0.879 0.943
第4次模拟 1.105 0.925
第5次模拟 1.206 0.909
第6次模拟 1.115 0.931
第7次模拟 1.056 0.957
第8次模拟 1.420 0.929
第9次模拟 1.127 0.922
第10次模拟 1.378 0.937
平均值 1.1585 0.9297
Competiton_2.txt
第1次模拟 1.432 0.898
第2次模拟 1.726 0.880
第3次模拟 1.648 0.882
第4次模拟 1.900 0.886
第5次模拟 1.856 0.902
第6次模拟 1.678 0.877
第7次模拟 1.897 0.883
第8次模拟 1.757 0.863
第9次模拟 1.476 0.887
第10次模拟 1.465 0.882
平均值 1.6635 0.8840
Competiton_3.txt
第1次模拟 1.082 0.977
第2次模拟 1.147 0.966
第3次模拟 1.008 0.974
第4次模拟 1.092 0.970
第5次模拟 1.108 0.976
第6次模拟 0.976 0.955
第7次模拟 1.102 0.957
第8次模拟 1.021 0.973
第9次模拟 0.941 0.966
第10次模拟 1.080 0.949
平均值 1.0557 0.9663

发布了6 篇原创文章 · 获赞 0 · 访问量 981

猜你喜欢

转载自blog.csdn.net/weixin_43767154/article/details/94038757