Introduzido:
Algum tempo atrás, fui ao banco para lidar com os negócios e havia tantas pessoas na fila. Demorou menos de 5 minutos para lidar com os negócios sozinho, mas esperei duas horas (acredito que muitas pessoas encontraram essa situação). Fiquei sem palavras com esse nível de serviço, mas o problema surge novamente. O banco deve abrir várias janelas para garantir a qualidade geral do serviço e a taxa de utilização de recursos? Em seguida, simularemos esse problema através da teoria da fila.
Introdução à teoria da fila
A teoria da fila é uma teoria e método matemático que estuda o fenômeno da coleta e dispersão aleatória de sistemas e a engenharia de trabalho de sistemas aleatórios. Também é conhecido como teoria dos sistemas de serviços aleatórios e é um ramo de pesquisa de operações. Vamos simplificar a teoria das filas abaixo e olhar para a figura a seguir primeiro:
Organizamos várias mesas de serviço azul no lado esquerdo da imagem, com clientes vermelhos que podem vir à direita e uma área de espera amarela no meio. Se uma recepção de serviço estiver ociosa, os clientes poderão receber serviços diretamente, caso contrário, precisam esperar na área amarela. O pedido de atendimento ao cliente adota o princípio do primeiro a chegar e do serviço atual. Agora, se soubermos a distribuição de probabilidade dos clientes, como podemos organizar várias mesas de serviço à esquerda para obter um melhor nível de serviço e garantir a taxa de uso do balcão de serviço? Em seguida, criaremos um modelo para simular esse problema.
A teoria da fila é implementada passo a passo
1) Para a teoria da fila, primeiro precisamos determinar os atributos do cliente, saiba quando o cliente chegar, o tempo de serviço necessário etc. Primeiro, criamos uma classe de cliente, onde especificamos o tempo máximo e mínimo para o atendimento ao cliente. Aqui, para simplificar, pensamos diretamente que o tempo de serviço é completamente aleatório:
classe pública CustomerBean {// Tempo mínimo de serviço privado estático int minsertTime = 3 * 1000; // Tempo máximo de serviço privado estático int maxservEtime = 15 * 1000; // O cliente atinge o tempo privado de longo tempo; // O cliente precisa de tempo de serviço privado int servetime; public CustomerBean () {// Defina o tempo de chegada de chegada = system.currenttimemillis (); // conjunto de atendimento ao cliente de conjunto aleatório servEtime = (int) (Math.random () * (MaxServEtime - MinservEtime) + Minestertime); }} 2) Definimos o cliente acima e, em seguida, precisamos definir uma fila na fila. Vamos primeiro olhar para os atributos da fila. Aqui, definimos uma matriz para salvar os clientes na fila, definir os intervalos de tempo mínimo e máximo para o próximo cliente chegar e a probabilidade de o cliente chegar (para ser explicado brevemente aqui, se o tempo de intervalo do próximo cliente for 3, mas o que é o que é o que o cliente é o que o cliente não é calculado para que o cliente seja o que o cliente não é calculado para o que o cliente é o que o cliente não é calculado para o que o cliente é o que o cliente é o que o cliente não é calculado para que o cliente seja o que o cliente não é calculado para que o cliente seja o que o cliente não é o que o cliente é o que o cliente não é calculado e que o cliente é o que o cliente não é calculado e que o cliente não é o que o cliente não é calculado para que o cliente seja o que o cliente não é que o cliente seja o que o cliente não é calculado e que o cliente não é que o cliente não seja calculado.
public class CustomerQuene {// Aguardando a fila do cliente Private LinkedList <CustomerBean> clientes = new LinkedList <SuterBean> (); // O mais curto tempo para o próximo cliente vir private int Mintime = 0; // o tempo máximo para o próximo cliente vir private int maxTime = 1 * 1000; // a probabilidade de próximos clientes Taxa dupla privada = 0,9; // Identifique se o sinalizador booleano privado do cliente = true; // o número máximo de pessoas na fila privado int maxwaitnum = 0; } 3) Quando há clientes e filas, configuramos um tópico para gerar clientes para gerar continuamente clientes. Aqui estão as distribuições de tempo e probabilidade mencionadas acima.
/ ***@Descrição: Gere o tópico do cliente*@versão: 1.1.0*/ classe privada CustomerThread estende o thread {private CustomerThread (nome da string) {super (nome); } @Override public void run () {while (sinalizador) {// Adicione um novo cliente no final da equipe if (math.random () <rate) {clusters.addlast (new CustomerBean ()); if (maxwaitnum <clients.size ()) {maxwaitnum = clients.size (); }} INTRIGN SleepTime = (int) (Math.random () * (MaxTime - Mintime) + Mintime); tente {timeUnit.millisEconds.sleep (SleepTime); } catch (Exceção e) {e.printStackTrace (); }}}}} 4) Se houver clientes na fila da fila para cortar no balcão de serviço gratuito, você precisará levar o cliente na cabeça da equipe para receber o serviço.
public Sincronized CustomerBean getCustomerBean () {if (clusters == NULL || Customer.size () <1) {return null; } return clients.removefirst (); } 5) Atributos e métodos relacionados ao cliente estão todos prontos. Vamos definir os atributos relacionados à mesa de serviço. Aqui, definimos diretamente o balcão de serviço como um tópico para definir alguns indicadores de serviço, como o número de clientes atendidos, o tempo total de espera, o tempo total de serviço, o tempo máximo de espera etc.
public class serntThread estende thread {// número de clientes de serviço privado static int customernum = 0; // Tempo total de espera privado estático int sumwaittime = 0; // TOTAL DE SERVIÇO TEMPO DE SERVIÇO PRIVADO ESTÁTICO INT SUMSSTETIME = 0; // Tempo máximo de espera privado estático int maxwaittime = 0; bandeira booleana privada = false; nome de string privado; } 6) O principal trabalho do serviço de serviço é servir os clientes. Aqui, escrevemos operações relacionadas ao atendimento aos clientes no método de execução do thread.
public void run () {flag = true; while (flag) {clientebean client = CustomerQuene.getCustomerquene (). getCustomerBean (); // Se o tópico do cliente tiver sido fechado e não houver clientes na fila, o tópico da mesa de serviço fecha e libera se (cliente == null) {if (! CustomerQuene.getCustomerquene (). Isflag ()) {flag = false; imprimir(); } continuar; } long agora = System.CurrentTimemillis (); int waittime = (int) (agora - cliente.getArriveTime ()); // salve o tempo máximo de espera se (waittime> maxwaittime) {maxwaittime = waittime; } // O tempo de sono é o tempo de serviço do cliente, que representa o período de serviço durante esse período de tempo atendendo aos clientes. Tente {timeUnit.millisEconds.sleep (cliente.getServEtime ()); } catch (Exceção e) {e.printStackTrace (); } System.err.println (nome + "Hora para atender os clientes:" + Customer.getServServTime () + "MS/T Cliente esperando:" + waittime + "ms"); Customernum ++; sumwaittime += waittime; SumsServETime += Customer.getServETime (); }} 7) Finalmente, escrevemos um modelo de teste para verificar o nível de serviço
/ ** *@Descrição: */ package com.lulei.opsearch.quene; importar java.util.Concurrent.TimeUnit; Public class Test {public static void main (string [] args) {// Abra o sistema de porta.out.println ("Abra a porta e pegue os clientes!"); bandeira booleana = true; CustomerQuene.getCustomerquene (); longo a = System.currenttimemillis (); int servicenum = 10; for (int i = 0; i <servicenum; i ++) {serntThread thread = new serntThread ("serviço de serviço"+i); thread.start (); } while (flag) {long b = System.currenttimemillis (); if (b - a> 1 * 60 * 1000 && sinaliza) {// FLAGLE FLAND = FALSE; CustomerQuene.getCustomerquene (). Close (); System.out.println ("Feche a porta e não pegue clientes!"); } System.out.println ("Tempo de execução do sistema:" + (b -a) + "ms"); System.out.println ("Tempo ocioso do sistema:" + ((b -a) * serntnum - serntThread.getSumsServETime ())); SerntThread.print (); tente {timeunit.seconds.sleep (2); } catch (Exceção e) {e.printStackTrace (); }}}} Resultados de execução
1) Início da operação
2) O cliente gera fechamento de threads
3) Nível de serviço final
Ao modificar o número de mesas de serviço, você pode avaliar quantas mesas de serviço devem ser configuradas na situação atual do cliente.
Código completo
1) Categoria do cliente
/ ** *@Descrição: */ package com.lulei.opsearch.quene; classe pública CustomerBean {// Tempo mínimo de serviço privado estático int minsertTime = 3 * 1000; // Tempo máximo de serviço privado estático int maxservEtime = 15 * 1000; // O cliente atinge o tempo privado de longo tempo; // O cliente precisa de tempo de serviço privado int servetime; public CustomerBean () {// Definir tempo de chegada ARRIVETIME = System.currenttimemillis (); // Defina aleatoriamente o tempo de atendimento ao cliente servEtime = (int) (Math.random () * (MaxServEtime - Mins ServETime) + Minestertime); } public static int getMinserStime () {return minserServETime; } public static void setMinserStTime (int minservEtime) {CustomerBean.MinserStETime = MIMSERVETIMENTE; } public static int getMaxServETime () {return maxServETime; } public static void setMaxServETime (int maxServEtime) {CustomerBean.MaxServETime = MaxServETime; } public long getArrIVETime () {return ArriveTime; } public void SetArriveTime (longo tempo de chegada) {this.arriveTime = ARVETIME; } public int getSeVetTime () {return servetime; } public void SetServTime (int servetime) {this.ServEtime = serveTime; }}2) Fila do cliente
/ ** *@Descrição: */ package com.lulei.opsearch.quene; importar java.util.LinkedList; importar java.util.Concurrent.TimeUnit; public class CustomerQuene {// Aguardando a fila do cliente Private LinkedList <CustomerBean> clientes = new LinkedList <SuterBean> (); // O mais curto tempo para o próximo cliente vir private int Mintime = 0; // o tempo máximo para o próximo cliente vir private int maxTime = 1 * 1000; // a probabilidade de o próximo cliente Taxa dupla privada = 0,9; // Identifique se os clientes continuam gerando sinalizador booleano privado = true; // Número máximo de pessoas na fila privado int maxwaitnum = 0; public int getMaxwaitnum () {return maxwaitnum; } public boolean isflag () {retornar sinalizador; } / ** * @return * @author: lulei * @description: coloque o cliente na cabeça da fila * / public sincronizado CustomerBean getCustomerBean () {if (clientes == NULL || Customer.size () <1) {return null; } return clients.removefirst (); } public void Close () {if (flag) {flag = false; }} / ** * @return * @author: lulei * @description: obtenha o número de clientes em espera * / public int getwaitCustomernum () {return clustermos.size (); } / ***@Descrição: Gere threads do cliente*@versão: 1.1.0* / classe privada CustomerThread Extende thread {private ClientThread (nome da string) {super (nome); } @Override public void run () {while (sinalizador) {// Adicione um novo cliente no final da equipe if (math.random () <rate) {clusters.addlast (new CustomerBean ()); if (maxwaitnum <clients.size ()) {maxwaitnum = clients.size (); }} INTRIGN SleepTime = (int) (Math.random () * (MaxTime - Mintime) + Mintime); tente {timeUnit.millisEconds.sleep (SleepTime); } catch (Exceção e) {e.printStackTrace (); }}}}} // Singleton Modo Inicie a classe estática privada CustomerQueneDao {cliente estático privado CustomerQuenequene = new CustomerQuene (); } private ClientEquene () {CustomerThread CustomerThread = new CustomerThread ("Tópico de geração do cliente"); conscienthread.start (); } public static CustomerQuene getCustomerquene () {return CustomerQueneDao.customerquene; } // singleton mode end 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 duplo getRate () {taxa de retorno; } public void setRate (Taxa dupla) {this.rate = rate; }} 3) Tópico da mesa de serviço
/ ** *@Descrição: */ package com.lulei.opsearch.quene; importar java.util.Concurrent.TimeUnit; importação com.lulei.util.parseutil; public class serntThread estende thread {// número de clientes de serviço privado static int customernum = 0; // Tempo total de espera privado estático int sumwaittime = 0; // TOTAL DE SERVIÇO TEMPO DE SERVIÇO PRIVADO ESTÁTICO INT SUMSSTETIME = 0; // Tempo máximo de espera privado estático int maxwaittime = 0; bandeira booleana privada = false; nome de string privado; public serntThread (nome da string) {super (nome); this.name = nome; } public static int getMaxwaittime () {return maxwaittime; } public static int getStumsSertTime () {return sumsServEtime; } @Override public void run () {flag = true; while (flag) {clientebean client = CustomerQuene.getCustomerquene (). getCustomerBean (); // Se o tópico do cliente tiver sido fechado e não houver clientes na fila, o tópico da mesa de serviço fecha e libera se (cliente == null) {if (! CustomerQuene.getCustomerquene (). Isflag ()) {flag = false; imprimir(); } continuar; } long agora = System.CurrentTimemillis (); int waittime = (int) (agora - cliente.getArriveTime ()); // salve o tempo máximo de espera se (waittime> maxwaittime) {maxwaittime = waittime; } // O tempo de sono é o tempo de serviço do cliente, que representa a tentativa do cliente {timeUnit.millisEconds.sleep (cliente.getServEtime ()); } catch (Exceção e) {e.printStackTrace (); } System.err.println (nome + "Hora para atender os clientes:" + cliente.getServEtime () + "MS/T Cliente esperando:" + waittime + "ms"); Customernum ++; sumwaittime += waittime; SumsServETime += Customer.getServETime (); }} public static void print () {if (personalizarum> 0) { System.out.println ("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Exercite o tempo de espera média do cliente e retenha dois lugares decimais System.out.println ("Tempo médio de espera para os clientes:" + parseutil.parsedoubletodouble ((sumwaittime * 1.0 /customermum), 2) + "ms"); Customernum), 2) + "MS"); 4) Teste o modelo
/ ** *@Descrição: */ package com.lulei.opsearch.quene; importar java.util.Concurrent.TimeUnit; Public class Test {public static void main (string [] args) {// Abra o sistema de porta.out.println ("Abra a porta e pegue os clientes!"); bandeira booleana = true; CustomerQuene.getCustomerquene (); longo a = System.currenttimemillis (); int servicenum = 10; for (int i = 0; i <servicenum; i ++) {serntThread thread = new serntThread ("serviço de serviço"+i); thread.start (); } while (flag) {long b = System.currenttimemillis (); if (b - a> 1 * 60 * 1000 && sinaliza) {// FLAGLE FLAND = FALSE; CustomerQuene.getCustomerquene (). Close (); System.out.println ("Feche a porta e não pegue clientes!"); } System.out.println ("Tempo de execução do sistema:" + (b -a) + "ms"); System.out.println ("Tempo ocioso do sistema:" + ((b -a) * serntnum - serntThread.getSumsServETime ())); SerntThread.print (); tente {timeunit.seconds.sleep (2); } catch (Exceção e) {e.printStackTrace (); }}}}O exposto acima é uma introdução detalhada aos princípios da teoria da fila de implementação de Java. Espero que seja útil para o aprendizado de todos.