欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)排隊論的原理

 更新時間:2016年02月01日 17:02:38   作者:xiaojimanman  
這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)排隊論的原理,對排隊論感興趣的小伙伴們可以參考一下

引入:

前段時間去銀行辦業(yè)務(wù),排隊的人那是真多,自己正式辦理業(yè)務(wù)也就不到5分鐘,但是卻足足等了兩個小時(相信很多人都遇到過這種情況),對這種服務(wù)水平真的是無語了,但是問題又來了,銀行應(yīng)該開幾個窗口,既能保證整體的服務(wù)質(zhì)量,又能保證資源資源的利用率呢?下面我們就通過排隊論來模擬這個問題。

排隊論簡介

      排隊論是研究系統(tǒng)隨機(jī)聚散現(xiàn)象和隨機(jī)系統(tǒng)工作工程的數(shù)學(xué)理論和方法,又稱隨機(jī)服務(wù)系統(tǒng)理論,為運籌學(xué)的一個分支。我們下面對排隊論做下簡化處理,先看下圖:

      我們在圖的左側(cè)安排若干個藍(lán)色服務(wù)臺,右側(cè)為可能會過來的紅色顧客,中間為黃色的等候區(qū),如果有服務(wù)臺處于空閑狀態(tài),顧客可以直接去接受服務(wù),否則就要在黃色區(qū)域等候,顧客服務(wù)的順序采用先到現(xiàn)服務(wù)的原則,現(xiàn)在如果我們知道顧客過來的概率分布,那么我們在左側(cè)安排幾個服務(wù)臺既能達(dá)到更好的服務(wù)水平,又能保證服務(wù)臺的使用率?下面我們就構(gòu)建模型來模擬這個問題。

排隊論分步實現(xiàn)

1)對于排隊論,我們首先要確定顧客屬性,知道顧客什么時候到達(dá),需要的服務(wù)耗時等,我們首先創(chuàng)建一個顧客類,在這里我們指定了顧客服務(wù)的最大、最小時間,這里我們?yōu)榱撕喕椭苯诱J(rèn)為服務(wù)時間完全隨機(jī):

public class CustomerBean { 
 //最小服務(wù)時間 
 private static int minServeTime = 3 * 1000; 
 //最大服務(wù)時間 
 private static int maxServeTime = 15 * 1000; 
 //顧客達(dá)到時間 
 private long arriveTime; 
 //顧客需要服務(wù)耗時 
 private int serveTime; 
  
 public CustomerBean() { 
  //設(shè)置到達(dá)時間 
  arriveTime = System.currentTimeMillis(); 
  //隨機(jī)設(shè)置顧客的服務(wù)時間 
  serveTime = (int) (Math.random() * (maxServeTime - minServeTime) + minServeTime); 
 } 
} 

2)上面我們定義了顧客,緊接著就需要定義一個排隊隊列,我們先看下隊列的屬性,這里我們定義一個數(shù)組,用它來保存排隊的顧客,定義下一個顧客到來的最小、最大時間間隔以及顧客來不來的概率(這里簡單說明下,如果下一個顧客的間隔時間是3,但是通過概率計算并為滿足,則這個顧客不進(jìn)入隊列,這樣設(shè)置的原因是盡可能的使顧客達(dá)到有很大的隨機(jī)性)和隊列中最大的排隊人數(shù)。

public class CustomerQuene { 
 //等待顧客隊列 
 private LinkedList<CustomerBean> customers = new LinkedList<CustomerBean>(); 
 //下一個顧客過來最短時間 
 private int minTime = 0; 
 //下一個顧客過來最大時間 
 private int maxTime = 1 * 1000; 
 //來顧客的概率 
 private double rate = 0.9; 
 //標(biāo)識是否繼續(xù)產(chǎn)生顧客 
 private boolean flag = true; 
 //最大排隊人數(shù) 
 private int maxWaitNum = 0; 
} 

3)顧客和排隊的隊列都有了,我們就設(shè)置一個產(chǎn)生顧客的線程,讓它不斷的產(chǎn)生顧客,這里就有我們上面說的時間和概率分布。

/** 
 *@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)如果隊列中有顧客排隊切有空閑的服務(wù)臺,就需要獲取隊頭的顧客去接受服務(wù)

public synchronized CustomerBean getCustomerBean() { 
 if (customers == null || customers.size() < 1) { 
  return null; 
 } 
 return customers.removeFirst(); 
} 

5)顧客相關(guān)的屬性和方法都已經(jīng)準(zhǔn)備好,下面就設(shè)置下服務(wù)臺相關(guān)的屬性,這里我們直接把服務(wù)臺設(shè)置成線程,定義一些服務(wù)指標(biāo),如服務(wù)的顧客數(shù)目、總等待時間、總服務(wù)時間、最大等待時間等。

public class ServantThread extends Thread{ 
 //服務(wù)顧客數(shù)目 
 private static int customerNum = 0; 
 //總等待時間 
 private static int sumWaitTime = 0; 
 //總服務(wù)時間 
 private static int sumServeTime = 0; 
 //最大等待時間 
 private static int maxWaitTime = 0; 
 private boolean flag = false; 
 private String name; 
} 

6)服務(wù)臺最主要的工作就是服務(wù)顧客,這里我們把服務(wù)顧客相關(guān)的操作寫到線程的run方法中。

public void run() { 
 flag = true; 
 while (flag) { 
  CustomerBean customer = CustomerQuene.getCustomerQuene().getCustomerBean(); 
  //如果顧客線程已經(jīng)關(guān)閉且隊列中沒有顧客,服務(wù)臺線程關(guān)閉釋放 
  if (customer == null) { 
   if (!CustomerQuene.getCustomerQuene().isFlag()) { 
    flag = false; 
    print(); 
   } 
   continue; 
  } 
  long now = System.currentTimeMillis(); 
  int waitTime = (int) (now - customer.getArriveTime()); 
  //保存最大的等待時間 
  if (waitTime > maxWaitTime) { 
   maxWaitTime = waitTime; 
  } 
  //睡眠時間為顧客的服務(wù)時間,代表這段時間在服務(wù)顧客 
  try { 
   TimeUnit.MILLISECONDS.sleep(customer.getServeTime()); 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
  System.err.println(name + " 服務(wù)顧客耗時:" + customer.getServeTime() + "ms\t顧客等待:" + waitTime + "ms"); 
  customerNum++; 
  sumWaitTime += waitTime; 
  sumServeTime += customer.getServeTime(); 
   
 } 
} 

7)最后我們編寫一個測試模型,來驗證服務(wù)水平

 /** 
 *@Description:  
 */ 
package com.lulei.opsearch.quene; 
 
import java.util.concurrent.TimeUnit; 
 
public class Test { 
 
 public static void main(String[] args) { 
  //開門 
  System.out.println("開門接客啦!"); 
  boolean flag = true; 
  CustomerQuene.getCustomerQuene(); 
  long a = System.currentTimeMillis(); 
  int servantNum = 10; 
  for (int i = 0; i < servantNum; i++) { 
   ServantThread thread = new ServantThread("服務(wù)臺" + i); 
   thread.start(); 
  } 
  while (flag) { 
   long b = System.currentTimeMillis(); 
   if (b - a > 1 * 60 * 1000 && flag) { 
    //關(guān)門 
    flag = false; 
    CustomerQuene.getCustomerQuene().close(); 
    System.out.println("關(guān)門不接客啦!"); 
   } 
   System.out.println("系統(tǒng)運行時間:" + (b -a) + "ms"); 
   System.out.println("系統(tǒng)空閑時間:" + ((b -a) * servantNum - ServantThread.getSumServeTime())); 
   ServantThread.print(); 
   try { 
    TimeUnit.SECONDS.sleep(2); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
  } 
 } 
 
} 

運行結(jié)果
1)運行開始

2)顧客產(chǎn)生線程關(guān)閉

3)最后服務(wù)水平

通過修改服務(wù)臺的個數(shù)就可以評估在當(dāng)前的顧客情況下應(yīng)該設(shè)置幾個服務(wù)臺。

完整代碼

1)顧客類

 /** 
 *@Description:  
 */ 
package com.lulei.opsearch.quene; 
 
public class CustomerBean { 
 //最小服務(wù)時間 
 private static int minServeTime = 3 * 1000; 
 //最大服務(wù)時間 
 private static int maxServeTime = 15 * 1000; 
 //顧客達(dá)到時間 
 private long arriveTime; 
 //顧客需要服務(wù)耗時 
 private int serveTime; 
  
 public CustomerBean() { 
  //設(shè)置到達(dá)時間 
  arriveTime = System.currentTimeMillis(); 
  //隨機(jī)設(shè)置顧客的服務(wù)時間 
  serveTime = (int) (Math.random() * (maxServeTime - minServeTime) + minServeTime); 
 } 
 
 public static int getMinServeTime() { 
  return minServeTime; 
 } 
 
 public static void setMinServeTime(int minServeTime) { 
  CustomerBean.minServeTime = minServeTime; 
 } 
 
 public static int getMaxServeTime() { 
  return maxServeTime; 
 } 
 
 public static void setMaxServeTime(int maxServeTime) { 
  CustomerBean.maxServeTime = maxServeTime; 
 } 
 
 public long getArriveTime() { 
  return arriveTime; 
 } 
 
 public void setArriveTime(long arriveTime) { 
  this.arriveTime = arriveTime; 
 } 
 
 public int getServeTime() { 
  return serveTime; 
 } 
 
 public void setServeTime(int serveTime) { 
  this.serveTime = serveTime; 
 } 
} 

2)顧客隊列

 /** 
 *@Description:  
 */ 
package com.lulei.opsearch.quene; 
 
import java.util.LinkedList; 
import java.util.concurrent.TimeUnit; 
 
public class CustomerQuene { 
 //等待顧客隊列 
 private LinkedList<CustomerBean> customers = new LinkedList<CustomerBean>(); 
 //下一個顧客過來最短時間 
 private int minTime = 0; 
 //下一個顧客過來最大時間 
 private int maxTime = 1 * 1000; 
 //來顧客的概率 
 private double rate = 0.9; 
 //標(biāo)識是否繼續(xù)產(chǎn)生顧客 
 private boolean flag = true; 
 //最大排隊人數(shù) 
 private int maxWaitNum = 0; 
  
 public int getMaxWaitNum() { 
  return maxWaitNum; 
 } 
  
 public boolean isFlag() { 
  return flag; 
 } 
 
 /** 
  * @return 
  * @Author:lulei 
  * @Description: 獲取排在隊頭的顧客 
  */ 
 public synchronized CustomerBean getCustomerBean() { 
  if (customers == null || customers.size() < 1) { 
   return null; 
  } 
  return customers.removeFirst(); 
 } 
  
 public void close() { 
  if (flag) { 
   flag = false; 
  } 
 } 
  
 /** 
  * @return 
  * @Author:lulei 
  * @Description: 獲取等待顧客數(shù)量 
  */ 
 public int getWaitCustomerNum() { 
  return customers.size(); 
 } 
  
 /** 
  *@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(); 
    } 
   } 
  } 
 } 
 
 //單例模式開始 
 private static class CustomerQueneDao { 
  private static CustomerQuene customerQuene = new CustomerQuene(); 
 } 
 private CustomerQuene() { 
  CustomerThread customerThread = new CustomerThread("顧客產(chǎn)生線程"); 
  customerThread.start(); 
 } 
 public static CustomerQuene getCustomerQuene() { 
  return CustomerQueneDao.customerQuene; 
 } 
 //單例模式結(jié)束 
  
 public int getMinTime() { 
  return minTime; 
 } 
  
 public void setMinTime(int minTime) { 
  this.minTime = minTime; 
 } 
  
 public int getMaxTime() { 
  return maxTime; 
 } 
  
 public void setMaxTime(int maxTime) { 
  this.maxTime = maxTime; 
 } 
 
 public double getRate() { 
  return rate; 
 } 
 
 public void setRate(double rate) { 
  this.rate = rate; 
 } 
} 

3)服務(wù)臺線程

 /** 
 *@Description:  
 */ 
package com.lulei.opsearch.quene; 
 
import java.util.concurrent.TimeUnit; 
 
import com.lulei.util.ParseUtil; 
 
public class ServantThread extends Thread{ 
 //服務(wù)顧客數(shù)目 
 private static int customerNum = 0; 
 //總等待時間 
 private static int sumWaitTime = 0; 
 //總服務(wù)時間 
 private static int sumServeTime = 0; 
 //最大等待時間 
 private static int maxWaitTime = 0; 
 private boolean flag = false; 
 private String name; 
  
 public ServantThread(String name) { 
  super(name); 
  this.name = name; 
 } 
  
 public static int getMaxWaitTime() { 
  return maxWaitTime; 
 } 
 
 public static int getSumServeTime() { 
  return sumServeTime; 
 } 
 
 @Override 
 public void run() { 
  flag = true; 
  while (flag) { 
   CustomerBean customer = CustomerQuene.getCustomerQuene().getCustomerBean(); 
   //如果顧客線程已經(jīng)關(guān)閉且隊列中沒有顧客,服務(wù)臺線程關(guān)閉釋放 
   if (customer == null) { 
    if (!CustomerQuene.getCustomerQuene().isFlag()) { 
     flag = false; 
     print(); 
    } 
    continue; 
   } 
   long now = System.currentTimeMillis(); 
   int waitTime = (int) (now - customer.getArriveTime()); 
   //保存最大的等待時間 
   if (waitTime > maxWaitTime) { 
    maxWaitTime = waitTime; 
   } 
   //睡眠時間為顧客的服務(wù)時間,代表這段時間在服務(wù)顧客 
   try { 
    TimeUnit.MILLISECONDS.sleep(customer.getServeTime()); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
   System.err.println(name + " 服務(wù)顧客耗時:" + customer.getServeTime() + "ms\t顧客等待:" + waitTime + "ms"); 
   customerNum++; 
   sumWaitTime += waitTime; 
   sumServeTime += customer.getServeTime(); 
    
  } 
 } 
  
 public static void print() { 
  if (customerNum > 0) { 
   System.out.println("--------------------------------------"); 
   System.out.println("服務(wù)顧客數(shù)目:" + customerNum); 
   System.out.println("最大等待時間:" + maxWaitTime); 
   System.out.println("等待顧客數(shù)目:" + CustomerQuene.getCustomerQuene().getWaitCustomerNum()); 
   System.out.println("最大等待顧客數(shù)目:" + CustomerQuene.getCustomerQuene().getMaxWaitNum()); 
   //輸出顧客平均等待時間,保留兩位小數(shù) 
   System.out.println("顧客平均等待時間:" + ParseUtil.parseDoubleToDouble((sumWaitTime * 1.0 / customerNum), 2) + "ms"); 
   System.out.println("顧客平均服務(wù)時間:" + ParseUtil.parseDoubleToDouble((sumServeTime * 1.0 / customerNum), 2) + "ms"); 
   System.out.println("系統(tǒng)總服務(wù)時間:" + sumServeTime + "ms"); 
  } 
 } 
} 

4)測試模型

 /** 
 *@Description:  
 */ 
package com.lulei.opsearch.quene; 
 
import java.util.concurrent.TimeUnit; 
 
public class Test { 
 
 public static void main(String[] args) { 
  //開門 
  System.out.println("開門接客啦!"); 
  boolean flag = true; 
  CustomerQuene.getCustomerQuene(); 
  long a = System.currentTimeMillis(); 
  int servantNum = 10; 
  for (int i = 0; i < servantNum; i++) { 
   ServantThread thread = new ServantThread("服務(wù)臺" + i); 
   thread.start(); 
  } 
  while (flag) { 
   long b = System.currentTimeMillis(); 
   if (b - a > 1 * 60 * 1000 && flag) { 
    //關(guān)門 
    flag = false; 
    CustomerQuene.getCustomerQuene().close(); 
    System.out.println("關(guān)門不接客啦!"); 
   } 
   System.out.println("系統(tǒng)運行時間:" + (b -a) + "ms"); 
   System.out.println("系統(tǒng)空閑時間:" + ((b -a) * servantNum - ServantThread.getSumServeTime())); 
   ServantThread.print(); 
   try { 
    TimeUnit.SECONDS.sleep(2); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
  } 
 } 
 
} 

以上就是關(guān)于Java實現(xiàn)排隊論的原理詳細(xì)介紹,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • microlog4android將Android Log日志寫到SD卡文件中實現(xiàn)方法

    microlog4android將Android Log日志寫到SD卡文件中實現(xiàn)方法

    這篇文章主要介紹了microlog4android將Android Log日志寫到SD卡文件中實現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 使用Java如何對復(fù)雜的數(shù)據(jù)類型排序和比大小

    使用Java如何對復(fù)雜的數(shù)據(jù)類型排序和比大小

    我相信大家在第一次接觸算法的時候,最先接觸的肯定也是從排序算法開始的,下面這篇文章主要給大家介紹了關(guān)于使用Java如何對復(fù)雜的數(shù)據(jù)類型排序和比大小的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • 基于Java回顧之多線程同步的使用詳解

    基于Java回顧之多線程同步的使用詳解

    在這篇文章里,我們關(guān)注線程同步的話題。這是比多線程更復(fù)雜,稍不留意,我們就會“掉到坑里”,而且和單線程程序不同,多線程的錯誤是否每次都出現(xiàn),也是不固定的,這給調(diào)試也帶來了很大的挑戰(zhàn)
    2013-05-05
  • Java的HashMap源碼解析

    Java的HashMap源碼解析

    這篇文章主要介紹了Java的HashMap源碼解析,HashMap是一個用于存儲Key-Value鍵值對的集合,每一個鍵值對是一個Node,后臺是用一個Node數(shù)組來存放數(shù)據(jù),這個Node數(shù)組就是HashMap的主干,需要的朋友可以參考下
    2023-11-11
  • 詳解java8在Collection中新增加的方法removeIf

    詳解java8在Collection中新增加的方法removeIf

    這篇文章主要介紹了詳解java8在Collection中新增加的方法removeIf的相關(guān)資料,需要的朋友可以參考下
    2018-01-01
  • jdk21環(huán)境配置詳細(xì)步驟記錄

    jdk21環(huán)境配置詳細(xì)步驟記錄

    JDK是整個Java開發(fā)的核心,它包含了Java的運行環(huán)境和Java工具,這篇文章主要給大家介紹了關(guān)于jdk21環(huán)境配置的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • springmvc如何進(jìn)行異常處理

    springmvc如何進(jìn)行異常處理

    這篇文章主要介紹了springmvc如何進(jìn)行異常處理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • Linux中Java開發(fā)常用軟件安裝方法總結(jié)

    Linux中Java開發(fā)常用軟件安裝方法總結(jié)

    這篇文章主要介紹了Linux中Java開發(fā)常用軟件安裝方法總結(jié),需要的朋友可以參考下
    2020-02-02
  • Java?hibernate延遲加載get和load的區(qū)別

    Java?hibernate延遲加載get和load的區(qū)別

    這篇文章主要介紹了Java?hibernate延遲加載get和load的區(qū)別,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • springboot+mysql+mybatis實現(xiàn)控制臺打印sql

    springboot+mysql+mybatis實現(xiàn)控制臺打印sql

    在Spring Boot中使用MyBatis與MySQL,并希望在控制臺打印SQL語句,可以通過配置MyBatis的日志級別來實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論