引入:
前段时间去银行办业务,排队的人那是真多,自己正式办理业务也就不到5分钟,但是却足足等了两个小时(相信很多人都遇到过这种情况),对这种服务水平真的是无语了,但是问题又来了,银行应该开几个窗口,既能保证整体的服务质量,又能保证资源资源的利用率呢?下面我们就通过排队论来模拟这个问题。
排队论简介
排队论是研究系统随机聚散现象和随机系统工作工程的数学理论和方法,又称随机服务系统理论,为运筹学的一个分支。我们下面对排队论做下简化处理,先看下图:
我们在图的左侧安排若干个蓝色服务台,右侧为可能会过来的红色顾客,中间为黄色的等候区,如果有服务台处于空闲状态,顾客可以直接去接受服务,否则就要在黄色区域等候,顾客服务的顺序采用先到现服务的原则,现在如果我们知道顾客过来的概率分布,那么我们在左侧安排几个服务台既能达到更好的服务水平,又能保证服务台的使用率?下面我们就构建模型来模拟这个问题。
排队论分步实现
1)对于排队论,我们首先要确定顾客属性,知道顾客什么时候到达,需要的服务耗时等,我们首先创建一个顾客类,在这里我们指定了顾客服务的最大、最小时间,这里我们为了简化就直接认为服务时间完全随机:
public class CustomerBean {
//最小服务时间
private static int minServeTime = 3 * 1000;
//最大服务时间
private static int maxServeTime = 15 * 1000;
//顾客达到时间
private long arriveTime;
//顾客需要服务耗时
private int serveTime;
public CustomerBean() {
//设置到达时间
arriveTime = System.currentTimeMillis();
//随机设置顾客的服务时间
serveTime = (int) (Math.random() * (maxServeTime - minServeTime) + minServeTime);
}
}
2)上面我们定义了顾客,紧接着就需要定义一个排队队列,我们先看下队列的属性,这里我们定义一个数组,用它来保存排队的顾客,定义下一个顾客到来的最小、最大时间间隔以及顾客来不来的概率(这里简单说明下,如果下一个顾客的间隔时间是3,但是通过概率计算并为满足,则这个顾客不进入队列,这样设置的原因是尽可能的使顾客达到有很大的随机性)和队列中最大的排队人数。
public class CustomerQuene {
//等待顾客队列
private LinkedList customers = new LinkedList();
//下一个顾客过来最短时间
private int minTime = 0;
//下一个顾客过来最大时间
private int maxTime = 1 * 1000;
//来顾客的概率
private double rate = 0.9;
//标识是否继续产生顾客
private boolean flag = true;
//最大排队人数
private int maxWaitNum = 0;
}
3)顾客和排队的队列都有了,我们就设置一个产生顾客的线程,让它不断的产生顾客,这里就有我们上面说的时间和概率分布。
/**
*@Description: 生成顾客线程
*@Version:1.1.0
*/
private class CustomerThread extends Thread {
private CustomerThread(String name) {
super(name);
}
@Override
public void run() {
while (flag) {
//队尾添加一个新顾客
if (Math.random() < rate) {
customers.addLast(new CustomerBean());
if (maxWaitNum < customers.size()) {
maxWaitNum = customers.size();
}
}
int sleepTime = (int) (Math.random() * (maxTime - minTime) + minTime);
try {
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
4)如果队列中有顾客排队切有空闲的服务台,就需要获取队头的顾客去接受服务
public synchronized CustomerBean getCustomerBean() {
if (customers == null || customers.size() < 1)