本文已参与「新人创作礼」活动,一起开启创作之路。

代码链接:github代码

一、 实验目的

应用M/M/1队列编程思想,模拟超市收银排队等待的过程,熟悉离散事件推进方式、队列建立java怎么读和提取方式。

二、 数学模型

1、 首先确定模型框架,即核心是创建一根事件轴和一支队列。先判定事件轴是否忙碌,是就根据时间先后顺序让顾客进入队列,否则推进事件

构建时序推进的离散事件仿真模型,github下载此处编写代码采用基于活动的方法推进仿真时钟,使用固定时间间隔和基于规则的方法来决定是否开始一个活动,在每到一javascript个固定的时间节点,就检查条件,判定此时处于哪个活动,并触发相应活动的条件,直到整个时间推进超出规定的阈值范围。

2监控家用远程手机. 简述事件调度法、活动服务器内存和台式机内存区别扫描法和进程交互法的异同。 区别(异): 事件调度法:面向事件,记录github汤姆事件发生的过程,处理每个时间发生时系统状态变化的结果; 活动扫描法:面向活动,记录每个活动开始与终止的时间,从而记录实体从一种状态变为另一种状态的过程。 进程交互法:面向进程,关注实体以及它所经历的事件/活动序列。 相同: 三种方法的核心都是事件按时间顺序发生,即按仿真时钟进行推进。

三、 编程实现与调试过程

1、 分析一下到达和离开的事件处理流程:

【某航】队列模型(MM1)设计与仿真

图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

分析:

  1. 通过仿真程序输出的结果和理论计算结果基本吻合,平均服务时间与最终计算的平均服务时间一致,平均逗留时间等于平均等待时间与平均服务时github汤姆github官网之和,表明该仿真程序的正确性。
  2. 前三组对比实验(1,2,3)保证平均服务时间和监控时监控钟终点不变,改变平均到达时间,可以看gitlab到当平均到达时间小于平均服务时间时,有很多顾客未被服务到,另外队列中平均等待顾客数特别多,平均等待时间非常长,服务器利用率接近100%;当两者相等时,能保证大部分顾客都被服务上,但队列中仍存在等待的情况,服务器利用率也高达98%;当平均到达时间github是什么大于平均服务时间时,基本每一位顾客都可以被服务到,队列中平均等待为0(小数点已经约去监控拍下东航客机坠落瞬间),但服务器利用率比较低,仅有59%。
  3. 对比实验(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代码

如果感觉对你有所帮助,不妨点个赞,关注一波,激励博主持续更监控安装新!