Il peut être traduit par un verrou à compte à rebours (compte à rebours). Inutile de dire que le verrou signifie, comme son nom l'indique, d'éviter les progrès. Ici, cela signifie que la méthode à compte à rebours.Await () bloquera le thread actuel avant que le compte à rebours soit 0.
CountdownLatch est une classe d'assistance synchrone qui permet à un ou plusieurs threads d'attendre qu'un ensemble d'opérations soit effectué dans d'autres threads.
CountdownLatch fonctionne similaire à la méthode thread.join () et peut être utilisé pour la collaboration entre un groupe de threads et un autre groupe de threads. Par exemple, le fil principal a besoin d'une série de préparatifs avant de faire un travail, et ce n'est que si toutes ces préparatifs sont terminés que le fil principal peut continuer son travail. Ces préparatifs sont indépendants les uns des autres, ils peuvent donc être exécutés simultanément pour augmenter la vitesse. Dans ce scénario, CountdownLatch peut être utilisé pour coordonner la planification entre les threads. À l'ère lorsque les threads ont été créés directement (avant Java 5.0), nous pouvons utiliser Thread.Join (). Une fois le JUC apparaît, car les threads dans le pool de thread ne peuvent pas être directement référencés, le compte à rebours doit être utilisé.
La classe CountdownLatch est un compteur synchrone. Lors de la construction, le paramètre int est passé. Ce paramètre est la valeur initiale du compteur. Chaque fois que le compte à rebours () est appelé, le compteur est décrémenté de 1 et le compteur est supérieur à 0, la méthode Await () bloquera le programme et continuera l'exécution. Le compte à rebours peut être considéré comme un verrou à compte à rebours, déclenchant un événement spécifique lorsque le nombre est réduit à 0. En utilisant cette fonctionnalité, le thread principal peut attendre la fin du thread enfant. Ce qui suit est un exemple d'une compétition d'athlètes simulée.
Un scénario d'application très typique de CountdownLatch est: il y a une tâche qui veut être exécutée vers le bas, mais vous devez attendre que d'autres tâches soient exécutées avant de pouvoir continuer à être exécutée vers le bas. Si notre tâche que nous voulons continuer à exécuter d'autres appels, la méthode Await () de l'objet CountdownLatch, et que les autres tâches appellent la méthode à compte à rebours () sur le même objet CountdownLatch après avoir exécuté leurs propres tâches, la tâche qui appelle la méthode Await () continuera de bloquer et d'attendre la valeur de comptage de l'objet CountdownLatch diminue à 0.
CountdownLatch Fonction Liste
CountdownLatch (int count) construit un compte à rebours initialisé avec un décompte donné. // Faites en sorte que le thread actuel attende jusqu'à ce que le verrou ne compte à zéro, sauf si le fil est interrompu. void Await () // fait attendre le thread actuel que le verrou ne compte à zéro, sauf si le thread est interrompu ou que le temps d'attente spécifié soit dépassé. Boolean attend (temps d'attente longue, unité de timeUnit) // décrément le nombre du verrou. Si le nombre atteint zéro, tous les fils d'attente seront libérés. void Countdown () // renvoie le nombre actuel. long getCount () // Renvoie une chaîne identifiant ce verrou et son statut. String toString ()
CountdownLatch Data Structure
Le diagramme de classe UML de CountdownLatch est le suivant:
La structure de données de CountdownLatch est simple, elle est implémentée via des "verrous partagés". Il contient des objets Sync, Sync est le type de synchronisation. Sync est une classe d'instance, qui hérite d'AQS.
Exemple de compte à rebours
Ce qui suit est implémenté via CountdownLatch: "le thread principal" attend "5 threads enfants" pour terminer le "travail spécifié (1000 ms)" avant de continuer à s'exécuter.
Importer java.util.concurrent.countDownLatch; Importer java.util.concurrent.cyclicBarrier; public classe CountDownlatchTest1 {private static int latch_size = 5; Le compte à rebours statique privé Donesignal; public static void main (String [] args) {try {donesignal = new CountdownLatch (latch_size); // Créer 5 nouvelles tâches pour (int i = 0; i <latch_size; i ++) new InnerThread (). Start (); System.out.println ("Main Await Begin."); // "Filant principal" attend l'achèvement de 5 tâches dans le pool de threads pour terminer Donesignal.Await (); System.out.println ("Main Await terminé."); } catch (InterruptedException e) {e.printStackTrace (); }} classe statique innerthread étend Thread {public void run () {try {Thread.Sleep (1000); System.out.println (thread.currentThread (). GetName () + "Sleep 1000ms."); // Soustraire la valeur de CountdownLatch par 1 Donesignal.CountDown (); } catch (InterruptedException e) {e.printStackTrace (); }}}} Résultats en cours:
Main Await commence.
La description du résultat: Le thread principal utilise Donesignal.Await () pour attendre que les autres threads diminuent Donesignal à 0. Les 5 autres threads de l'InnerTread, chacun soustrait la valeur de Donesignal par 1 via DoneSignal.CountDown (); Lorsque Donesignal est 0, Main continuera de s'exécuter après avoir été réveillé.
PS: Différence entre le compte à rebours et CyclicBarrier:
(1) La fonction de CountdownLatch est de permettre aux threads 1 ou n d'attendre que d'autres threads terminent l'exécution; tandis que CyclicArrier permet à N threads d'attendre les uns les autres.
(2) le compteur du compte à rebours ne peut pas être réinitialisé; Le comptoir de la barrière cyclique peut être utilisé après réinitialisation, il est donc appelé une barrière en boucle.