Présenté:
Il y a quelque temps, je suis allé à la banque pour gérer les affaires, et il y avait tellement de gens en ligne. Il a fallu moins de 5 minutes pour gérer les affaires par moi-même, mais j'ai attendu deux heures (je crois que beaucoup de gens ont rencontré cette situation). J'étais sans voix sur ce niveau de service, mais le problème se pose à nouveau. La banque devrait ouvrir plusieurs fenêtres pour assurer la qualité globale du service et le taux d'utilisation des ressources? Ensuite, nous simulerons ce problème grâce à la théorie des files d'attente.
Introduction à la théorie de la file d'attente
La théorie de la file d'attente est une théorie et une méthode mathématiques qui étudient le phénomène de la collecte et de la dispersion aléatoires des systèmes et l'ingénierie de travail des systèmes aléatoires. Il est également connu comme la théorie des systèmes de services aléatoires et est une branche de la recherche opérationnelle. Simplifions la théorie de la file d'attente ci-dessous et examinons d'abord la figure suivante:
Nous organisons plusieurs bureaux de service bleu sur le côté gauche de l'image, avec des clients rouges qui peuvent venir à droite et une zone d'attente jaune au milieu. Si un service de service est inactif, les clients peuvent recevoir directement des services, sinon ils doivent attendre dans la zone jaune. L'ordre du service à la clientèle adopte le principe du premier arrivé et du service actuel. Maintenant, si nous connaissons la distribution de probabilité des clients à venir, comment pouvons-nous organiser plusieurs bureaux de service à gauche pour atteindre un meilleur niveau de service et assurer le taux d'utilisation du service de service? Ensuite, nous allons construire un modèle pour simuler ce problème.
La théorie de la file d'attente est mise en œuvre étape par étape
1) Pour la théorie de la file d'attente, nous devons d'abord déterminer les attributs du client, savoir quand le client arrive, l'heure de service requise, etc. Nous créons d'abord une classe client, où nous spécifions le temps maximum et minimum pour le service client. Ici, afin de simplifier, nous pensons directement que le temps de service est complètement aléatoire:
classe publique CustomerBean {// Temps de service minimum privé static int minServertime = 3 * 1000; // Temps de service maximum privé static int maxServertime = 15 * 1000; // Client atteint le temps privé long Arrivetime; // Client a besoin de temps de service privé int ne sertEtime; public CustomerBean () {// Set Arrival Heure ArrivalTime = System.CurrentTimemillis (); // Time de service client aléatoire Service ServeTime = (int) (math.random () * (maxServertime - MinServiTime) + MinServiTime); }} 2) Nous définissons le client ci-dessus, puis nous devons définir une file d'attente. Voyons d'abord les attributs de la file d'attente. Ici, nous définissons un tableau pour enregistrer les clients en file d'attente, définissons les intervalles de temps minimum et maximum pour que le prochain client arrive et que la probabilité que le client arrive (pour être brièvement expliquée ici, si l'intervalle de la file du client est 3, mais il est calculé par la probabilité et satisfait, le client n'entrera pas dans la file d'attente. La raison de ce cadre est de faire un grand aléatoire autant que possible) et le nombre maximal de la qualité de la file.
classe publique CustomerQuene {// en attente de la file d'attente client privé LinkedList <SitretBean> Clients = new LinkedList <SitretBean> (); // le plus court pour que le client suivant vienne privé int mintime = 0; // le temps maximum pour que le client suivant vienne privé int maxtime = 1 * 1000; // La probabilité de double taux privé à venir = 0,9; // Identifiez si le Flag booléen privé du client = true; // le nombre maximum de personnes faisant la queue privée int maxwaitnum = 0; } 3) Lorsqu'il y a des clients et des files d'attente, nous avons configuré un fil pour générer des clients pour générer en continu des clients. Voici les distributions de temps et de probabilité que nous avons mentionnées ci-dessus.
/ ** * @ Description: Générer le thread client * @ version: 1.1.0 * / classe privée CustomerThread étend Thread {private CustomerThread (String Name) {super (name); } @Override public void run () {while (flag) {// ajouter un nouveau client à la fin de l'équipe if (math.random () <rate) {Clients.Addlast (new CustomerBean ()); if (maxwaitnum <clients.size ()) {maxwaitnum = clients.size (); }} int sleeptime = (int) (math.random () * (maxtime - mintime) + mintime); essayez {timeunit.milliseconds.sleep (temps de sommeil); } catch (exception e) {e.printStackTrace (); }}}}} 4) S'il y a des clients dans la file d'attente pour couper le service de service gratuit, vous devez mettre le client en tête de l'équipe pour recevoir le service.
CustomerBean Synchronisé public GetCustomerBean () {if (Clients == NULL || CLIENTS.SIZE () <1) {return null; } return Clients.RemoveFirst (); } 5) Les attributs et méthodes liés au client sont tous prêts. Définissons les attributs liés à Service Desk. Ici, nous définissons directement le service de service sur un fil pour définir certains indicateurs de service, tels que le nombre de clients desservis, le temps d'attente total, le temps de service total, le temps d'attente maximum, etc.
classe publique ServitantThread étend Thread {// Nombre de clients de service privé static int CustomEnnum = 0; // temps d'attente total privé static int sumwaittime = 0; // Temps de service total private statique int sumServertime = 0; // Temps d'attente maximal privé static int maxwaittime = 0; Flag booléen privé = false; nom de chaîne privé; } 6) Le travail principal du service de service est de servir les clients. Ici, nous écrivons des opérations liées au service des clients dans la méthode d'exécution du fil.
public void run () {flag = true; while (Flag) {CustomerBean Customer = CustomerQuene.getCustomerQuene (). getCustomerBean (); // Si le thread client a été fermé et qu'il n'y a pas de clients dans la file d'attente, le thread de service de service ferme et libère si (client == null) {if (! CustomerQue.getCustomerQuene (). ISFLAG ()) {flag = false; imprimer(); } continuer; } long maintenant = System.currentTimemillis (); int wait time = (int) (maintenant - client.getArveTime ()); // Enregistrez le temps d'attente maximal si (temps de serve> maxwaittime) {maxwaittime = temps de serve; } // Le temps de sommeil est le temps de service du client, qui représente la période de service pendant cette période de service des clients. Essayez {timeunit.milliseconds.sleep (client.getServertime ()); } catch (exception e) {e.printStackTrace (); } System.err.println (Name + "Temps pour servir les clients:" + Customer.getSerserServetime () + "MS / T Client Waiting:" + Wait Time + "MS"); CustomerNum ++; SumwaitTime + = temps de serve; SUMSERVETime + = Customer.getServertime (); }} 7) Enfin, nous écrivons un modèle de test pour vérifier le niveau de service
/ ** * @ Description: * / package com.lulei.opsearch.quene; Importer java.util.concurrent.TimeUnit; Test de classe publique {public static void main (String [] args) {// Ouvrez la porte System.out.println ("Ouvrez la porte et ramassez les clients!"); Flag booléen = true; CustomerQuene.getCustomerQuene (); long a = System.currenttimemillis (); int Servicenum = 10; for (int i = 0; i <Servicenum; i ++) {ServantThread Thread = new ServantThread ("Service Desk" + i); thread.start (); } while (flag) {long b = System.currenttimemillis (); if (b - a> 1 * 60 * 1000 && flag) {// close flag = false; ClientQuene.getCustomerQuene (). Close (); System.out.println ("Fermez la porte et ne ramassez pas les clients!"); } System.out.println ("Temps d'exécution du système:" + (b -a) + "ms"); System.out.println ("Temps d'inactivité du système:" + ((b -a) * ServantNum - ServantThread.getsumServertime ())); SertantThread.print (); essayez {timeunit.seconds.sleep (2); } catch (exception e) {e.printStackTrace (); }}}} Résultats en cours d'exécution
1) Début de l'opération
2) Le client génère la fermeture du thread
3) Niveau de service final
En modifiant le nombre de bureaux de service, vous pouvez évaluer le nombre de bureaux de service qui doivent être configurés dans la situation client actuelle.
Code complet
1) Catégorie de client
/ ** * @ Description: * / package com.lulei.opsearch.quene; classe publique CustomerBean {// Temps de service minimum privé static int minServertime = 3 * 1000; // Temps de service maximum privé static int maxServertime = 15 * 1000; // Client atteint le temps privé long Arrivetime; // Client a besoin de temps de service privé int ne sertEtime; public CustomerBean () {// Set Arrival Heure ArriveTime = System.CurrentTimemillis (); // Définissez au hasard le service client Service ServeTime = (int) (math.random () * (maxServertime - MinServertime) + MinServeTime); } public static int getMinservnetime () {return minServertime; } public static void setMInservertime (int minServertime) {clientBean.minservertime = MinServicetime; } public static int getMaxServertime () {return maxServertime; } public static void setMaxServertime (int maxServertime) {CustomerBean.maxServertime = maxServertime; } public long getArriveTime () {return arrivetime; } public void setArriveTime (long ArriveTime) {this.arrivetime = arrivetime; } public int getServertime () {return ServeTime; } public void setServertime (int ServeTime) {this.serveTime = ServeTime; }}2) File d'attente du client
/ ** * @ Description: * / package com.lulei.opsearch.quene; import java.util.linkedlist; Importer java.util.concurrent.TimeUnit; classe publique CustomerQuene {// en attente de la file d'attente client privé LinkedList <SitretBean> Clients = new LinkedList <SitretBean> (); // le plus court pour que le client suivant vienne privé int mintime = 0; // le temps maximum pour que le client suivant vienne privé int maxtime = 1 * 1000; // La probabilité de double taux privé client à venir = 0,9; // Identifiez si les clients continuent de générer un drapeau booléen privé = true; // Nombre maximum de personnes en file d'attente privé int maxwaitnum = 0; public int getmaxwaitnum () {return maxwaitnum; } public boolean isflag () {return drapeau; } / ** * @return * @author: LULEI * @Description: Obtenez le client dans la tête de la file d'attente * / public synchronisé CustomerBean getCustomerBean () {if (clients == null || clients.size () <1) {return null; } return Clients.RemoveFirst (); } public void close () {if (flag) {flag = false; }} / ** * @return * @author: LULEI * @Description: Obtenez le nombre de clients en attente * / public int GetWaitCustomMennum () {return Clients.Size (); } / ** * @ Description: Générer le thread client * @ Version: 1.1.0 * / classe privée CustomerThread étend Thread {private CustomerThread (String Name) {super (name); } @Override public void run () {while (flag) {// ajouter un nouveau client à la fin de l'équipe if (math.random () <rate) {Clients.Addlast (new CustomerBean ()); if (maxwaitnum <clients.size ()) {maxwaitnum = clients.size (); }} int sleeptime = (int) (math.random () * (maxtime - mintime) + mintime); essayez {timeunit.milliseconds.sleep (temps de sommeil); } catch (exception e) {e.printStackTrace (); }}}}} // mode singleton start private static class CustomerQuenedao {private static clientQuene CustomerQuene = new CustomerQuene (); } private CustomerQuene () {CustomerThread CustomerThread = new CustomerThread ("Customer Generation Thread"); CustomerThread.start (); } public static CustomerQuene getCustomerQuene () {return CustomerQuenedao.CustomerQuene; } // mode singleton end public int getMintime () {return mintime; } public void setMintime (int mintime) {this.mintime = mintime; } public int getMAxtime () {return maxtime; } public void setMextime (int maxtime) {this.mAxtime = maxtime; } public double getrate () {taux de retour; } public void setRate (double rate) {this.rate = rate; }} 3) Filetage du bureau de service
/ ** * @ Description: * / package com.lulei.opsearch.quene; Importer java.util.concurrent.TimeUnit; import com.lulei.util.parseutil; classe publique ServitantThread étend Thread {// Nombre de clients de service privé static int CustomEnnum = 0; // temps d'attente total privé static int sumwaittime = 0; // Temps de service total private statique int sumServertime = 0; // Temps d'attente maximal privé static int maxwaittime = 0; Flag booléen privé = false; nom de chaîne privé; Public ServantThread (nom de chaîne) {super (nom); this.name = name; } public static int getMaxWaitTime () {return maxWaitTime; } public static int getsumServertime () {return sumServertime; } @Override public void run () {flag = true; while (Flag) {CustomerBean Customer = CustomerQuene.getCustomerQuene (). getCustomerBean (); // Si le thread client a été fermé et qu'il n'y a pas de clients dans la file d'attente, le thread de service de service ferme et libère si (client == null) {if (! CustomerQue.getCustomerQuene (). ISFLAG ()) {flag = false; imprimer(); } continuer; } long maintenant = System.currentTimemillis (); int wait time = (int) (maintenant - client.getArveTime ()); // Enregistrez le temps d'attente maximal si (temps de serve> maxwaittime) {maxwaittime = temps de serve; } // L'heure de sommeil est l'heure de service du client, qui représente l'essai du client {timeunit.milliseconds.sleep (client.getServertime ()); } catch (exception e) {e.printStackTrace (); } System.err.println (Name + "Temps pour servir les clients:" + Customer.getServertime () + "MS / T Customer Waiting:" + Wait Time + "MS"); CustomerNum ++; SumwaitTime + = temps de serve; SUMSERVETime + = Customer.getServertime (); }} public static void print () {if (Customernum> 0) { System.out.println ("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Sortie le temps d'attente moyen du client et conserve deux décimales System.out.println ("Temps d'attente moyen pour les clients:" + parseutil.parsedoubletodouble ((SumwaitTime * 1.0 / Customernerm), 2) + "MS"); CustomEnnum), 2) + "MS"); 4) Testez le modèle
/ ** * @ Description: * / package com.lulei.opsearch.quene; Importer java.util.concurrent.TimeUnit; Test de classe publique {public static void main (String [] args) {// Ouvrez la porte System.out.println ("Ouvrez la porte et ramassez les clients!"); Flag booléen = true; CustomerQuene.getCustomerQuene (); long a = System.currenttimemillis (); int Servicenum = 10; for (int i = 0; i <Servicenum; i ++) {ServantThread Thread = new ServantThread ("Service Desk" + i); thread.start (); } while (flag) {long b = System.currenttimemillis (); if (b - a> 1 * 60 * 1000 && flag) {// close flag = false; ClientQuene.getCustomerQuene (). Close (); System.out.println ("Fermez la porte et ne ramassez pas les clients!"); } System.out.println ("Temps d'exécution du système:" + (b -a) + "ms"); System.out.println ("Temps d'inactivité du système:" + ((b -a) * ServantNum - ServantThread.getsumServertime ())); SertantThread.print (); essayez {timeunit.seconds.sleep (2); } catch (exception e) {e.printStackTrace (); }}}}Ce qui précède est une introduction détaillée aux principes de la mise en œuvre de la théorie de la file d'attente Java. J'espère que cela sera utile à l'apprentissage de tous.