소개 :
얼마 전, 나는 사업을 처리하기 위해 은행에 갔고, 많은 사람들이 줄을 서서있었습니다. 혼자서 사업을 처리하는 데 5 분도 채 걸리지 않았지만 2 시간 동안 기다렸습니다 (많은 사람들 이이 상황을 발견했다고 생각합니다). 나는이 서비스 수준에 대해 말이 없었지만 문제는 다시 발생합니다. 은행은 전반적인 서비스 품질과 리소스 활용률을 보장하기 위해 여러 창문을 열어야합니까? 다음으로 큐 이론을 통해이 문제를 시뮬레이션 할 것입니다.
대기열 이론 소개
큐잉 이론은 시스템의 무작위 수집 및 분산 현상과 임의의 시스템의 작동 공학을 연구하는 수학적 이론과 방법입니다. 그것은 랜덤 서비스 시스템의 이론으로도 알려져 있으며 운영 연구의 지부입니다. 아래의 대기열 이론을 단순화하고 다음 그림을 먼저 살펴 보겠습니다.
우리는 그림의 왼쪽에 몇 개의 파란색 서비스 책상을 배열하고 오른쪽에 올 수있는 빨간색 고객과 중간에 노란 대기 영역이 있습니다. 서비스 데스크가 유휴 상태 인 경우 고객은 서비스를 직접받을 수 있습니다. 그렇지 않으면 노란색 영역에서 기다려야합니다. 고객 서비스 순서는 선착순 및 현재 서비스의 원칙을 채택합니다. 이제 고객의 확률 분포를 알고 있다면 왼쪽에 여러 서비스 책상을 어떻게 배열하여 더 나은 서비스 수준을 달성하고 서비스 데스크의 사용률을 보장 할 수 있습니까? 다음 으로이 문제를 시뮬레이션하기위한 모델을 구축 할 것입니다.
대기열 이론은 단계별로 구현됩니다
1) 대기열 이론의 경우 먼저 고객 속성을 결정하고 고객이 도착하는시기, 필요한 서비스 시간 등을 알아야합니다. 먼저 고객 클래스를 만듭니다. 여기서 고객 서비스의 최대 및 최소 시간을 지정합니다. 여기서 단순화하기 위해 서비스 시간이 완전히 무작위라고 생각합니다.
공개 클래스 CustomerBean {// 최소 서비스 시간 개인 정적 int minservetime = 3 * 1000; // 최대 서비스 시간 개인 정적 int maxservetime = 15 * 1000; // 고객은 시간이 오래 시간에 도달합니다. // 고객 요구 서비스 시간 개인 int servetime; public customerbean () {// 도착 시간 세트 시간 도착 시간 = System.CurrentTimeMillis (); // 임의의 설정 고객 서비스 시간 servetime = (int) (math.random () * (maxservetime -minservetime) + minservetime); }} 2) 위의 고객을 정의한 다음 큐 큐를 정의해야합니다. 먼저 대기열의 속성을 살펴 보겠습니다. 여기서 우리는 대기열 고객을 저장하기위한 배열을 정의하고, 다음 고객이 도착할 수있는 최소 및 최대 시간 간격을 정의하고 고객이 올 확률 (다음 고객의 간격 시간이 3 인 경우 간단히 설명 할 수 있지만 확률을 통해 계산되고 만족되는 경우 고객이 최대의 무작위에 도달하지 못하게하는 것입니다.)
공개 클래스 CustomerQuene {// 고객 대기열을 기다리고 개인 LinkedList <FustomerBean> 고객 = New LinkedList <CustomerBean> (); // 다음 고객이 Private Int Mintime = 0이 오는 가장 짧은 시간; // 다음 고객이 Private Int Maxtime = 1 * 1000의 최대 시간; // 다가오는 확률 고객 개인 이중 속도 = 0.9; // 고객 개인 부울 플래그 = true; // 개인의 최대 인원 수는 개인 int maxwaitnum = 0; } 3) 고객과 대기열이 있으면 고객을 지속적으로 생성 할 수있는 고객을 생성 할 스레드를 설정했습니다. 위에서 언급 한 시간과 확률 분포는 다음과 같습니다.
/ ***@description : 고객 스레드 생성*@버전 : 1.1.0*/ private Class CustomerThread는 스레드 {private customerthread (문자열 이름) {super (name); } @override public void run () {while (flag) {// 팀 끝에서 새 고객을 추가하면 (math.random () <rate) {customer.addlast (new CustomerBean ()); if (maxwaitnum <customer.size ()) {maxwaitnum = customer.size (); }} int sleeptime = (int) (math.random () * (maxtime -mintime) + mintime); try {timeUnit.milliseconds.sleep (sleeptime); } catch (예외 e) {e.printstacktrace (); }}}}} 4) 대기열에 무료 서비스 데스크를 자르기 위해 대기열에 고객이있는 경우 팀장의 고객에게 서비스를 받도록해야합니다.
public synchronized customerbean getCustomerBean () {if (customer == null || customer.size () <1) {return null; } return customer.removeFirst (); } 5) 고객 관련 속성 및 방법이 모두 준비되었습니다. 서비스 데스크 관련 속성을 설정하겠습니다. 여기서 우리는 서비스 데스크를 스레드로 직접 설정하여 제공된 고객 수, 총 대기 시간, 총 서비스 시간, 최대 대기 시간 등과 같은 일부 서비스 표시기를 정의합니다.
공개 클래스 Servantthread는 스레드를 확장합니다. // 총 대기 시간 비공개 정적 int sumwaittime = 0; // 총 서비스 시간 비공개 정적 int sumservetime = 0; // 최대 대기 시간 개인 정적 int maxwaittime = 0; 개인 부울 플래그 = 거짓; 개인 문자열 이름; }
6) 서비스 데스크의 주요 작업은 고객에게 서비스를 제공하는 것입니다. 여기서 우리는 고객에게 스레드의 실행 방법에 서비스를 제공하는 것과 관련된 작업을 작성합니다.
public void run () {flag = true; while (flag) {customerbean customer = customerquene.getCustomerQuene (). getCustomerBean (); // 고객 스레드가 닫히고 대기열에 고객이없는 경우 서비스 데스크 스레드가 닫히고 if (customer == null) {if (! customerQuene.getCustomerQuene (). isflag ()) {flag = false; 인쇄(); } 계속하다; } long now = System.CurrentTimeMillis (); int waittime = (int) (지금 - 고객 .getArrivetime ()); // (대기 시간> MaxWaitTime) if 최대 대기 시간을 저장합니다. {MaxWaitTime = 대기 시간; } // 수면 시간은 고객의 서비스 시간이며,이 기간 동안 고객에게 서비스를 제공하는 서비스 기간을 나타냅니다. try {timeUnit.milliseconds.sleep (customer.getServetime ()); } catch (예외 e) {e.printstacktrace (); } system.err.println (이름 + "고객 서비스를위한 시간 :" + customer.getServeservetime () + "MS/T 고객 대기 :" + Waittime + "MS"); CustomerNum ++; Sumwaittime += 대기 시간; sumservetime += customer.getServetime (); }} 7) 마지막으로, 우리는 서비스 수준을 확인하기 위해 테스트 모델을 작성합니다.
/ ** *@description : */ package com.lulei.opsearch.quene; java.util.concurrent.timeUnit import; 공개 클래스 테스트 {public static void main (String [] args) {// 도어 시스템을 엽니 다. 부울 플래그 = 참; CustomerQuene.getCustomerQuene (); long a = system.currenttimeMillis (); int servicenum = 10; for (int i = 0; i <servicenum; i ++) {servantthread 스레드 = new servantthread ( "Service Desk"+i); thread.start (); } while (flag) {long b = system.currenttimemillis (); if (b -a> 1 * 60 * 1000 && flag) {// flag = false; CustomerQuene.getCustomerQuene (). Close (); System.out.println ( "문을 닫고 고객을 데리러 가지 마십시오!"); } system.out.println ( "시스템 실행 시간 :" + (b -a) + "ms"); System.out.println ( "시스템 유휴 시간 :" + ((b -a) * servantnum -servantthread.getSumservetime ())); servantthread.print (); try {timeUnit.seconds.sleep (2); } catch (예외 e) {e.printstacktrace (); }}}} 실행 결과
1) 작동 시작
2) 고객은 스레드 닫기를 생성합니다
3) 최종 서비스 수준
서비스 데스크 수를 수정하면 현재 고객 상황에서 얼마나 많은 서비스 데스크를 설정 해야하는지 평가할 수 있습니다.
완전한 코드
1) 고객 카테고리
/ ** *@description : */ package com.lulei.opsearch.quene; 공개 클래스 CustomerBean {// 최소 서비스 시간 개인 정적 int minservetime = 3 * 1000; // 최대 서비스 시간 개인 정적 int maxservetime = 15 * 1000; // 고객은 시간이 오래 시간에 도달합니다. // 고객 요구 서비스 시간 개인 int servetime; public customerbean () {// 도착 시간을 설정합니다. // 고객 서비스 시간 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; java.util.linkedList 가져 오기; java.util.concurrent.timeUnit import; 공개 클래스 CustomerQuene {// 고객 대기열을 기다리고 개인 LinkedList <FustomerBean> 고객 = New LinkedList <CustomerBean> (); // 다음 고객이 Private Int Mintime = 0이 오는 가장 짧은 시간; // 다음 고객이 Private Int Maxtime = 1 * 1000의 최대 시간; // 오는 확률 고객 개인 이중 속도 = 0.9; // 고객이 개인 부울 플래그 = true를 계속 생성하는지 여부를 식별합니다. // 최대 인원 수용 개인 int maxwaitnum = 0; public int getmaxwaitnum () {return maxwaitnum; } public boolean isflag () {return flag; } / ** * @return * @author : lulei * @description : 대기열의 머리에 고객을 확보하십시오 * / public synchronized customerbean getCustomerBean () {if (customer == null || customers.size () <1) {return null; } return customer.removeFirst (); } public void close () {if (flag) {flag = false; }} / ** * @return * @author : lulei * @description : 대기 고객 수를 얻습니다 * / public int getwaitcustomernum () {return customer.size (); } / ***@description : 고객 스레드 생성*@버전 : 1.1.0* / private Class CustomerThread는 스레드 {private customerthread (문자열 이름) {super (name); } @override public void run () {while (flag) {// 팀 끝에서 새 고객을 추가하면 (math.random () <rate) {customer.addlast (new CustomerBean ()); if (maxwaitnum <customer.size ()) {maxwaitnum = customer.size (); }} int sleeptime = (int) (math.random () * (maxtime -mintime) + mintime); try {timeUnit.milliseconds.sleep (sleeptime); } catch (예외 e) {e.printstacktrace (); }}}}} // 싱글 톤 모드 시작 개인 정적 클래스 고객 고객 Quendao {private static customerQuene CustomerQuene = new CustomerQuene (); } private CustomerQuene () {CustomerThread CustomerThread = New CustomerTheRdread ( "고객 생성 스레드"); customerthread.start (); } public static customerquene getCustomerQuene () {return customerQuendao.CustomerQuene; } // 싱글 톤 모드 엔드 공개 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) 서비스 데스크 스레드
/ ** *@description : */ package com.lulei.opsearch.quene; java.util.concurrent.timeUnit import; import com.lulei.util.parseutil; 공개 클래스 Servantthread는 스레드를 확장합니다. // 총 대기 시간 비공개 정적 int sumwaittime = 0; // 총 서비스 시간 비공개 정적 int sumservetime = 0; // 최대 대기 시간 개인 정적 int maxwaittime = 0; 개인 부울 플래그 = 거짓; 개인 문자열 이름; 공무원 (문자열 이름) {super (name); this.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 (); // 고객 스레드가 닫히고 대기열에 고객이없는 경우 서비스 데스크 스레드가 닫히고 if (customer == null) {if (! customerQuene.getCustomerQuene (). isflag ()) {flag = false; 인쇄(); } 계속하다; } long now = System.CurrentTimeMillis (); int waittime = (int) (지금 - 고객 .getArrivetime ()); // (대기 시간> MaxWaitTime) if 최대 대기 시간을 저장합니다. {MaxWaitTime = 대기 시간; } // 수면 시간은 고객의 서비스 시간이며 고객의 시도를 나타내는 {timeUnit.milliseconds.sleep (customer.getServetime ()); } catch (예외 e) {e.printstacktrace (); } system.err.println (이름 + "고객 서비스를위한 시간 :" + customer.getServetime () + "MS/T 고객 대기 :" + Waittime + "MS"); CustomerNum ++; Sumwaittime += 대기 시간; sumservetime += customer.getServetime (); }} public static void print () {if (CustomerNum> 0) { System.out.println("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // 고객의 평균 대기 시간을 출력하고 소수점 이하 두 자리를 유지합니다. out.println ( "고객의 평균 대기 시간 :" + parseutil.parsedoubletodouble (Sumwaittime * 1.0 /customernum), "ms"( "고객을위한 평균 서비스 시간 :" + parseutil. CustomerNum), 2) + "MS"); 4) 모델을 테스트하십시오
/ ** *@description : */ package com.lulei.opsearch.quene; java.util.concurrent.timeUnit import; 공개 클래스 테스트 {public static void main (String [] args) {// 도어 시스템을 엽니 다. 부울 플래그 = 참; CustomerQuene.getCustomerQuene (); long a = system.currenttimeMillis (); int servicenum = 10; for (int i = 0; i <servicenum; i ++) {servantthread 스레드 = new servantthread ( "Service Desk"+i); thread.start (); } while (flag) {long b = system.currenttimemillis (); if (b -a> 1 * 60 * 1000 && flag) {// flag = false; CustomerQuene.getCustomerQuene (). Close (); System.out.println ( "문을 닫고 고객을 데리러 가지 마십시오!"); } system.out.println ( "시스템 실행 시간 :" + (b -a) + "ms"); System.out.println ( "시스템 유휴 시간 :" + ((b -a) * servantnum -servantthread.getSumservetime ())); servantthread.print (); try {timeUnit.seconds.sleep (2); } catch (예외 e) {e.printstacktrace (); }}}}위의 것은 Java가 대기열 이론을 구현하는 원칙에 대한 자세한 소개입니다. 모든 사람의 학습에 도움이되기를 바랍니다.