本文已参与「新人创作礼」活动,一起开启创作之路。
代码链接:github代码
一、 实验目的
应用M/M/1队列编程思想,模拟超市收银排队等待的过程,熟悉离散事件推进方式、队列建立java怎么读和提取方式。
二、 数学模型
1、 首先确定模型框架,即核心是创建一根事件轴和一支队列。先判定事件轴是否忙碌,是就根据时间先后顺序让顾客进入队列,否则推进事件
构建时序推进的离散事件仿真模型,github下载此处编写代码采用基于活动的方法推进仿真时钟,使用固定时间间隔和基于规则的方法来决定是否开始一个活动,在每到一javascript个固定的时间节点,就检查条件,判定此时处于哪个活动,并触发相应活动的条件,直到整个时间推进超出规定的阈值范围。
2监控家用远程手机. 简述事件调度法、活动服务器内存和台式机内存区别扫描法和进程交互法的异同。 区别(异): 事件调度法:面向事件,记录github汤姆事件发生的过程,处理每个时间发生时系统状态变化的结果; 活动扫描法:面向活动,记录每个活动开始与终止的时间,从而记录实体从一种状态变为另一种状态的过程。 进程交互法:面向进程,关注实体以及它所经历的事件/活动序列。 相同: 三种方法的核心都是事件按时间顺序发生,即按仿真时钟进行推进。
三、 编程实现与调试过程
1、 分析一下到达和离开的事件处理流程:
图1 编程流程图(活动扫描法) 代码采用Javgithub中文官网网页a编写,JDK>=1.8均可运行该程序,具体的流程实现如下:- 初始化:输入平均到达时间,顾客平均服务时间,监控时钟的终点时刻
- 执行下列循环直到监控时钟到达终点时刻:
- 若监控时钟位于服务开始时间和服务结束时间之间:
- 输出此时队列中正在排队的人数,监控时钟切换下一个时间;
- 若监控时钟不位于在两者服务器租用多少钱一年之间,且服务开始时间小于服务结束github官网时间(代表下一个顾客的到来):
- 若排队序列为空:
- 执行服务活动,并计算出来服务结束的时间,将事件添加到结束github中文官网网页的事件中,总服务数++,计算并更新总逗留时间Total_q,总等待时间Tojava语言tal_w,总服务时间Total_s,计算下一个顾客到达时间作为服务开java环境变量配置始时间;
- 若排队序列不为空:
- 添加该事Git件Event到排队序列末尾,计算下一个顾客到达时间作为服务开始时间;
- 若排队序列为空:
- 若监控时钟不位于不在两者之间,且服务开始gitlab时间大于等于服务结束时间(代表当前顾客已经被服务结束):
- 若排队序列为空:
- 定义服务结束时间为无穷大,计算下一个顾客到达时间作为服务开始时间github官网登陆入口;
- 若排队序列不为空:
- 弹出监控眼排队序列java是什么意思中的下一位顾客github中文官网网页,执行服务活动,并计算出来服务结束的时间,将事件添加到结束的事件中,总服务数++,计算并更监控app下载新总逗留时间Tota服务器租用l_q,总等待时间Total_w服务器操作系统,总服务时间Tota监控摄像头l_s,计算下一个顾客到达时间;
- 若排队序列为空:
2、 给出输入参数(平均到达时间,平均服务时间,时钟截止时监控眼间)、输出参数(顾客数目,服务顾客数,平均执行时间,队列中平均等github是什么待客户数,服务器利用率)的服务器系统具体值,可以用图或表的方式展示多次仿真的结果值
运行Main.java中的main函数,得到如下输出:
改变输入参数,用表格的方式统计输出结果:
编号 | 平均到达时监控家用远程手机间ta | 平均服务时间ts | 监控时钟终点 | 顾客数目 | 服务顾客数 | 队列中平均等待顾客数 | 平均等待时间Tw | 平均逗留时间Tq | 平均服务时间Ts | 服务器利用率 |
---|---|---|---|---|---|---|---|---|---|---|
1 | 0.01 | 0.015 | 100 | 9835 | 6634 | 26 | 1gitee0.647 | 15.800 | 0.015 | 0.999监控系统 |
2 | 0.015 | 0.015 | 100 | 6612 | 6459 | 6 | 1.163 | 1.206 | 0.015 | 0.9java模拟器83 |
3 | 0.02 | 0.015 | 100 | 3974 | 3972 | 0 | 0.040 | 0.055 | 0.015 | 0.598 |
4 | 0.015 | 0.015 | 50 | 3445 | 3305 | 5 | 1.178 | 1.243 | 0.01监控摄像头5 | 0.988 |
5 | 0.015 | 0.015 | 120 | 8086 | 7810 | 6 | 1.187 | 1.232 | 0.015 | 0.989 |
分析:
- 通过仿真程序输出的结果和理论计算结果基本吻合,平均服务时间与最终计算的平均服务时间一致,平均逗留时间等于平均等待时间与平均服务时github汤姆间github官网之和,表明该仿真程序的正确性。
- 前三组对比实验(1,2,3)保证平均服务时间和监控时监控钟终点不变,改变平均到达时间,可以看gitlab到当平均到达时间小于平均服务时间时,有很多顾客未被服务到,另外队列中平均等待顾客数特别多,平均等待时间非常长,服务器利用率接近100%;当两者相等时,能保证大部分顾客都被服务上,但队列中仍存在等待的情况,服务器利用率也高达98%;当平均到达时间github是什么大于平均服务时间时,基本每一位顾客都可以被服务到,队列中平均等待为0(小数点已经约去监控拍下东航客机坠落瞬间),但服务器利用率比较低,仅有59%。
- 对比实验(2,4,5)保证平均服务时间和平均到达时间不变,监控时钟即仿真时长改变,可以看到,被服务giticomfort是什么轮胎顾服务器租用客总人数基本呈现等比例的缩放,平均值基本都保持不变,说明仿真时长基本不对平均结果影响。
总之,通过以上仿真实验可以得出结论,当平均到达时间约等于平均服务时间时,可以兼顾服务器高利用率的同时,让队列中的人数也不至于过多,另外此时大部github是什么分顾服务器怎么搭建客也可以被服务到。考虑到超市的实际情况,工作日人流量较小,周末人流量较大,要在考虑经济情况与成本的前提下,做出适当调整。
Controller.java
/**************************
* M/M/1 核心类 Controller
**************************/
package mm1;
import java.util.*;
import java.util.Random;
public class Controller {
public static final int BIRTH = 0;
public static final int DEATH = 1;
LinkedList<Event> schedule; // 事件队列
double clock; // 时钟
double endTime; // 时钟终止时间
double nextArrival; // 服务开始事件
double nextDeparture; // 服务结束时间
double ta; // 平均到达时间
double ts; // 平均服务时间
ArrayList<Double> checkpoints; // 监控测点
int numChecks; // 监控测点数
double Tq,Tw,Ts;
int w, q;
int requests, serviced;
/* 初始化 */
public Controller(double ta, double ts, double endTime) {
this.ta = ta;
this.ts = ts;
this.endTime = endTime;
checkpoints = new ArrayList<Double>();
double n = 0;
while (n < endTime) {
numChecks++;
n += exponential(ta);
checkpoints.add(n);
}
clock = 0;
schedule = new LinkedList<Event>();
nextArrival = exponential(1/ta);
nextDeparture = Double.POSITIVE_INFINITY;
Tq = 0; Tw = 0; Ts = 0;
w= 0; q = 0;
requests = 0; serviced = 0;
}
/* 下一个顾客到达 */
public void birthHandler(double time) {
if (schedule.isEmpty()) { // 队列为空,执行服务
scheduleDeath(time);
}
else { // 队列不为空,添加此顾客到队列中
schedule.add(new Event(time,BIRTH));
}
nextArrival += exponential(1/ta);
}
/* 当前服务结束 */
public void deathHandler() {
schedule.remove(); // 事件移除
if (!schedule.isEmpty()) { // 队列不为空:弹出执行队列中的任务
Event next = schedule.remove();
scheduleDeath(next.getTime());
} else{
// 队列为空,此时服务器空闲,等待下一任务
nextDeparture = Double.POSITIVE_INFINITY;
nextArrival += exponential(1/ta);
}
}
/* 服务执行,计算相关参数 */
public void scheduleDeath(double arrivalTime) {
nextDeparture = clock + exponential(1/ts); // 本次服务结束时间
schedule.addFirst(new Event(nextDeparture,DEATH));
serviced++; // 总服务数
Tq += (nextDeparture - arrivalTime); // 总逗留时间
Tw += (clock - arrivalTime); // 总等待时间
Ts += (nextDeparture - clock); // 总服务时间
}
/* 监控输出 */
public void monitorHandler() {
int cur_q = schedule.size();
int cur_w = (cur_q > 0) ? (schedule.size() - 1) : 0;
w += cur_w;
q += cur_q;
checkpoints.remove(0);
}
/* 指数分布生成函数 */
public static double exponential(double lambda) {
Random r = new Random();
double x = Math.log(1-r.nextDouble())/(-lambda);
return x;
}
/* 主函数 */
public void run() {
while (clock < endTime) {
if (checkpoints.get(0) < nextArrival && checkpoints.get(0) < nextDeparture) {
// 监控时刻位于服务发生时
clock = checkpoints.get(0);
monitorHandler();
}
else if (nextArrival <= nextDeparture) { // 下一个顾客的到来
clock = nextArrival;
birthHandler(nextArrival);
requests++;
}
else { // 服务结束
clock = nextDeparture;
deathHandler();
}
}
printStats();
}
public void printStats() {
// 输出相关参数
System.out.println("相关计算参数输出:");
System.out.println("顾客数目requests: " + requests);
System.out.println("服务顾客数serviced: " + serviced);
System.out.println("队列中平均等待客户数q = " + q/numChecks);
System.out.println("平均等待时间Tw = " + Tw/requests);
System.out.println("平均逗留时间Tq = " + Tq/serviced);
System.out.println("平均服务时间Ts = " + Ts/serviced);
System.out.println("服务器利用率 = " + Ts/endTime);
}
}
Event.java
/**************************
* M/M/1 事件类
**************************/
package mm1;
public class Event {
private double time;
private int type;
public Event(double t, int e) {
this.time = t;
this.type = e;
}
public double getTime() {
return time;
}
public int getType() {
return type;
}
}
Main.java
/********************
* M/M/1 队列模型
*******************/
package mm1;
public class Main {
public static void main(String[] args) {
double ta = 0.015; // 平均到达时间
double ts = 0.015; // 平均服务时间
double length = 100; // 监控时钟终点
Controller c1 = new Controller(ta,ts,length);
System.out.println("仿真 1: 平均到达时间ta = " + ta + ", 平均服务时间ts = " + ts + ", 监控时钟终点 length = " + length);
c1.run();
System.out.println("仿真结束");
}
}
代码链接:github代码
如果感觉对你有所帮助,不妨点个赞,关注一波,激励博主持续更监控安装新!