Cet article parle principalement des collections impliquées dans la concurrence. Pour les collections ordinaires, veuillez vous référer à [Présentation de la collection Java]
1. Qu'est-ce que BlockingQueue
BlockingQueue est une file d'attente de blocage. D'après le blocage des mots, on peut voir que l'accès à une file d'attente de blocage peut provoquer un blocage dans certains cas. Il y a deux principaux cas bloqués:
1. Lorsque la file d'attente est pleine, elle sera en cours.
2. Lorsque la file d'attente est vide, elle sera hors de la file d'attente.
Par conséquent, lorsqu'un thread essaie de filer une file d'attente déjà complète, elle sera bloquée à moins qu'un autre thread ne fasse l'opération de file d'attente; De même, lorsqu'un thread essaie de filer une file d'attente vide, il sera bloqué à moins qu'un autre thread ne dispose de la file d'attente.
En Java, l'interface BlockingQueue est située dans le package java.util.concurrent (fourni dans la version Java 5). D'après les caractéristiques de la file d'attente de blocage introduite ci-dessus, on peut voir que la file d'attente de blocage est en file d'attente.
2. Comment utiliser BlockingQueue
Les files d'attente de blocage sont principalement utilisées dans les scénarios de producteur / consommateur. L'image suivante montre une production de threads et un scénario de consommation de fil:
Le fil responsable de la production crée en continu de nouveaux objets et les insère dans la file d'attente de blocage jusqu'à ce que la limite supérieure de cette file d'attente soit atteinte. Une fois que la file d'attente a atteint sa limite supérieure, le thread de production sera bloqué jusqu'à ce que le thread consommé consomme la file d'attente. De même, le fil responsable de la consommation consomme constamment des objets de la file d'attente jusqu'à ce que la file d'attente soit vide. Lorsque la file d'attente est vide, le thread de consommation sera bloqué à moins qu'un nouvel objet dans la file d'attente ne soit inséré.
3. Méthodes dans l'interface BlockingQueue
Il existe quatre ensembles de méthodes pour bloquer les files d'attente pour effectuer insert , remove et examine respectivement. Lorsque les opérations correspondant à chaque ensemble de méthodes ne peuvent pas être exécutées immédiatement, il y aura différentes réactions. Le tableau suivant répertorie ces méthodes de manière classifiée:
| - | Lance l'exception | Valeur spéciale | Blocs | Se terminer |
|---|---|---|---|---|
| Insérer | Ajouter (o) | offre (o) | mettre (o) | Offre (o, temps mort, timeUnit) |
| Retirer | Supprimer (o) | sondage() | prendre() | sondage (temps mort, timeunit) |
| Examiner | élément() | peek () |
Les caractéristiques correspondantes de ces quatre ensembles de méthodes sont:
1. ThrowSException: si l'opération ne peut pas être effectuée immédiatement, une exception sera lancée.
2. VALUE SPÉCIAL: Si l'opération ne peut pas être effectuée immédiatement, une valeur spéciale sera retournée, généralement vraie ou fausse
3. Blocs: Si l'opération ne peut pas être effectuée immédiatement, l'opération sera bloquée
4. Times-Out: Si l'opération ne peut pas être effectuée immédiatement, l'opération sera bloquée à l'heure spécifiée. Si le temps spécifié n'est pas exécuté, une valeur spéciale sera renvoyée, ce qui est généralement vrai ou faux.
Il convient de noter que nous ne pouvons pas insérer null dans le BlockingQueue, sinon NullPointerException sera signalée.
4. Classe d'implémentation BlockingQueue
BlockingQueue n'est qu'une interface dans le package java.util.concurrent . Lorsque nous l'utilisons spécifiquement, nous utilisons ses classes d'implémentation. Bien sûr, ces classes d'implémentation sont également situées dans le package java.util.concurrent . Dans Java 6, les classes d'implémentation de BlockingQueue sont principalement les suivantes:
1. ArrayBlockingQueue
2. DelayQueue
3. LinkedBlockingQueue
4. PriorityBlockingQueue
5. Synchronousqueue
Ci-dessous, nous présenterons ces classes d'implémentation séparément.
4.1 ArrayBlockingQueue
ArrayBlockingQueue est une file d'attente de blocage limitée, et son implémentation interne est un tableau. La signification de la limite signifie que sa capacité est limitée, nous devons spécifier sa taille de capacité lorsqu'elle est initialisée et que la taille de la capacité ne peut pas être modifiée une fois qu'elle est spécifiée.
ArrayBlockingQueue stocke les données de la première manière. L'objet nouvellement inséré est la queue et l'objet nouvellement déplacé est la tête. Voici un exemple d'initialisation et d'utilisation de ArrayBlockingQueue:
BlockingQueue Queue = new ArrayBlockingQueue (1024); queue.put ("1"); objet objet = queue.Take ();4.2 DelayQueue
Ce que DelayQueue bloque, ce sont ses éléments internes. Les éléments de DelayQueue doivent implémenter l'interface java.util.concurrent.Delayed . La définition de cette interface est très simple:
L'interface publique retardée s'étend comparable <layed> {Long Getdelay (unité de tempsUnit);} La valeur de retour de getDelay() est l'heure de maintien avant la libération de l'élément de file d'attente. Si 0 ou une负值est renvoyée, cela signifie que l'élément a expiré et doit être libéré. À l'heure actuelle, DelayEdQueue libérera cet objet via sa méthode take() .
Comme on peut le voir à partir de la définition d'interface retardée ci-dessus, il hérite également de l'interface Comparable . En effet, les éléments de la demande retardée doivent être triés. D'une manière générale, nous trions par priorité du temps d'expiration de l'élément.
Exemple 1: spécifiez un temps d'expiration pour un objet
Tout d'abord, nous définissons un élément, qui doit implémenter l'interface retardée
La classe publique DelayEdElement met en œuvre retardé {privé long expiré; long retard privé; nom de chaîne privé; DelayEdElement (String ElementName, Long Delay) {this. name = elementName; ce. retard = retard; expiré = (delage + système. CurrentTimemillis ()); } @Override public int compareto (retardé o) {deltEdElement cached = (delayedElement) o; return cached.getExpired ()> expiré? 1: -1; } @Override public long getdelay (timeunit unit) {return (expired - System. CurrentTimemillis ()); } @Override public String toString () {return "DelayeDelement [delay =" + delay + ", name =" + name + "]"; } public long getExpired () {return expired; }}Réglez le temps d'expiration de cet élément à 3s
classe publique DelayQueUeExample {public static void main (String [] args) lève InterruptedException {DelayQueue <ladeDelement> queue = new DelayQueue <> (); DelayEdElement ele = new DelayeDelement ("Cache 3 secondes", 3000); queue.put (ele); Système. out.println (queue.take ()); }}Exécutez cette fonction principale et nous pouvons constater que nous devons attendre 3 secondes avant d'imprimer cet objet.
En fait, il existe de nombreux scénarios d'application pour DelayQueue, tels que les connexions de clôture chronométrées, les objets de cache, le traitement du délai d'expiration et d'autres scénarios. Prenons l'examen de l'étudiant à titre d'exemple pour permettre à tout le monde de comprendre plus profondément l'utilisation de DelayQueue.
Exemple 2: Traitez tous les étudiants de l'examen comme un retardque, celui qui termine les questions qui les publient d'abord
Tout d'abord, nous construisons un objet étudiant
classe publique Student implémente Runnable, retardé {Nom de la chaîne privée; // Nom Private Long Costtime; // Temps pour le test Questions Private Long Fination name = name; ce. CostTime = CostTime; Système finalTime = CostTime +. CurrentTimemillis (); } @Override public void run () {System. out.println (nom + "Soumettre le papier, le temps" + CostTime / 1000); } @Override public long getdelay (timeunit unit) {return (finiTime - System. CurrentTimemillis ()); } @Override public int compareto (retardé o) {étudiant autre = (étudiant) o; Retour Costtime> = Autre. Cost temps? 1: -1; }}Ensuite, construisez un objet enseignant pour passer l'examen aux élèves
Classe publique Professeur {static final int étudiant_size = 30; public static void main (String [] args) lève InterruptedException {random r = new random (); // Considérez tous les étudiants comme une file d'attente de retard de retard <Student> Students = new DelayQueue <Student> (); // Construisez un pool de threads pour permettre aux étudiants de "faire leurs devoirs" exécutorService exec = exécutors.newFixEdThreadpool (Student_Size); pour (int i = 0; i <étudiant_size; i ++) {// initialisez le nom et le temps de l'élève pour faire les étudiants de test.put (nouveau étudiant ("Student" + (i + 1), 3000 + r.Nextint (10000))); } // Démarrez le test while (! Students.iSempty ()) {exec.execute (Students.Take ()); } exec.shutdown (); }}Jetons un coup d'œil aux résultats en cours d'exécution:
Étudiant 2 Soumettre le document, 3
Étudiant 1 remettre des papiers, en prenant 5
Étudiant 5 Soumettre le journal, 7
Étudiant 4 Soumettez le journal, en prenant 8
Étudiant 3 Soumettre le journal, 11
Grâce aux résultats en cours d'exécution, nous pouvons constater que chaque étudiant "soumettra le document" après l'arrivée de l'heure de début spécifiée ( selon la méthode GetDelay () ) et le document sera d'abord soumis ( selon la méthode compareto ( )).
En regardant son code source, vous pouvez voir que l'implémentation interne de DelayQueue utilise PriorityQueue et un verrou:
4.3 LinkedBlockingQueue
La configuration de la taille de file d'attente de blocage LinkedBlockingQueue est facultative. Si nous spécifions une taille lors de l'initialisation, elle est bornée et si elle n'est pas spécifiée, elle est bornée. On dit qu'il est sans limites, mais en fait, la taille par défaut est une capacité Integer.MAX_VALUE . Son implémentation interne est une liste liée.
Comme ArrayBlockingQueue, LinkedBlockingQueue stocke également les données de la première manière. L'objet nouvellement inséré est la queue et l'objet nouvellement déplacé est la tête. Voici un exemple d'initialisation et de fabrication de LinkedBlockingQueue:
BlockingQueue <string> non lié = new LinkedBlockerQueue <string> (); BlockingQueue <string> Boundhed = new LinkedBlockingQueue <string> (1024); Boundted.put ("Value"); String Value = Bounted.Take ();4.4 PriorityBlockingQueue
PriorityBlockingQueue est une file d'attente sans limites, et ses règles de tri sont les mêmes que java.util.PriorityQueue . Il convient de noter que les objets nuls peuvent être insérés dans PriorityBlockingQueue.
Tous les objets insérés dans PriorityBlockingQueue doivent implémenter l'interface java.lang.Comparable , et les règles de tri prioritaires de file d'attente sont définies en fonction de notre implémentation de cette interface.
De plus, nous pouvons obtenir un itérateur de PriorityBlockingQueue, mais cet itérateur ne garantit pas l'itération dans l'ordre prioritaire.
Donnons un exemple pour illustrer. Tout d'abord, nous définissons un type d'objet, qui doit implémenter l'interface comparable:
Classe publique PriorityElement implémente comparable <priorityElement> {private int priority; // define priority priorityElement (int priority) {// initialize priority this.priority = priority;} @ overRidepublic int compareto (priorityElement o) {// tri by priory size return priority> = o.getpriority ()? 1: -1;} public int getPriority () {return priority;} public void setPriority (int priority) {this.priority = priority;} @ overRidePublic String toString () {return "priorityElement [priority =" + priority + "]";}}Ensuite, nous définissons au hasard la priorité à la file d'attente
classe publique PriorityBlockerEUeExample {public static void main (String [] args) lance InterruptedException {priorityBlockerEue <priorityElement> filey = new priorityBlockingQueue <> (); pour (int i = 0; i <5; i ++) {aléatoire aléatoire = new random (); PriorityElement ele = new priorityElement (random.nextint (10)); queue.put (ele); } while (! queue.isempty ()) {System.out.println (queue.take ()); }}}Découvrez les résultats en cours:
PriorityElement [priority = 3]
PriorityElement [priority = 4]
PriorityElement [prioritaire = 5]
PriorityElement [priority = 8]
PriorityElement [priority = 9]
4.5 synchrone
Un seul élément est autorisé à l'intérieur de la file d'attente synchrone. Lorsqu'un thread insère un élément, il sera bloqué à moins que l'élément ne soit consommé par un autre thread.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.