Bloquer des files d'attente à Java
1. Qu'est-ce qu'une file d'attente de blocage?
Une file d'attente de blocage (BlockingQueue) est une file d'attente qui prend en charge deux opérations supplémentaires. Ces deux opérations supplémentaires sont:
Lorsque la file d'attente est vide, le fil qui récupère l'élément attendra que la file d'attente devienne non vide.
Lorsque la file d'attente est pleine, le fil qui stocke les éléments attendra que la file d'attente soit disponible.
Les files d'attente de blocage sont souvent utilisées dans des scénarios de producteurs et de consommateurs. Les producteurs sont des threads qui ajoutent des éléments aux files d'attente, et les consommateurs sont des threads qui prennent des éléments des files d'attente. Une file d'attente de blocage est le conteneur où le producteur stocke les éléments, et le consommateur ne prend que des éléments du conteneur.
2. Bloquer la file d'attente à Java
Sept files d'attente de blocage sont fournies dans le JDK:
ArrayBlockingQueue
ArrayBlockingQueue est une file d'attente de blocage limitée implémentée à l'aide de tableaux. Cette file d'attente trie les éléments selon le premier principe de sortie (FIFO). Par défaut, les visiteurs ne sont pas garantis d'accéder équitablement. La file d'attente dite assez accessible fait référence à tous les fils de producteur bloqués ou threads de consommation. Lorsque la file d'attente est disponible, la file d'attente est accessible dans l'ordre du blocage. Autrement dit, le fil de producteur qui bloque d'abord peut d'abord insérer des éléments dans la file d'attente, et le fil de consommation qui bloque d'abord peut d'abord obtenir des éléments de la file d'attente. Normalement, le débit est réduit afin d'assurer l'équité . Nous pouvons créer une file d'attente de blocage équitable en utilisant le code suivant:
ArrayBlockingQueue Fairqueue = New ArrayBlockingQueue (1000, true);
L'équité de son accès est obtenue grâce à la serrure ReentrantLock.
LinkedBlockingQueue
LinkedBlockingQueue est une file d'attente de blocage limitée implémentée avec des listes liées. La longueur par défaut et maximale de cette file d'attente est Integer.max_value. Cette file d'attente trie les éléments selon le premier principe de sortie.
PriorityBlockingQueue
PriorityBlockingQueue est une file d'attente illimitée qui prend en charge la priorité. Par défaut, les éléments sont organisés par ordre naturel et les règles de commande des éléments peuvent également être spécifiées via le comparateur du comparateur. Les éléments sont organisés par ordre croissant.
Ralentissement
DelayQueue est une file d'attente de blocage illimitée qui prend en charge l'acquisition retardée d'éléments. La file d'attente est implémentée à l'aide de PriorityQueue. Les éléments de la file d'attente doivent implémenter l'interface retardée et lors de la création d'un élément, vous pouvez spécifier le temps qu'il faut pour obtenir l'élément actuel de la file d'attente. Les éléments ne peuvent être extraits de la file d'attente que lorsque le retard expire. Nous pouvons utiliser DelayQueue dans les scénarios d'application suivants:
Conception du système de cache: DelayQueue peut être utilisée pour enregistrer la période de validité des éléments de cache, et un fil peut être utilisé pour interroger le degré. Une fois que l'élément peut être obtenu à partir du retardque, cela signifie que la période de validité du cache est arrivée.
Horaire de tâches planifié. Utilisez DelayQueue pour enregistrer les tâches et le temps d'exécution qui seront exécutés le jour. Une fois la tâche obtenue à partir du delayque, il commencera à s'exécuter. Par exemple, TimerQueue est implémenté à l'aide de DelayQueue.
Comment implémenter l'interface retardée
Nous pouvons nous référer à la classe PlanEdFutureTask dans ScheduledThreadPoolExecutor. Cette classe implémente l'interface retardée. Premièrement: lors de la création d'un objet, utilisez du temps pour enregistrer lorsque l'objet peut être utilisé avant l'enregistrement. Le code est le suivant:
SchedouledFutureTask (Runnable R, V Result, Long NS, longue période) {super (r, résultat); this.time = ns; this.period = période; this.sensceNumber = Sequencer.GetAndInCment ();}Utilisez ensuite GetDelay pour interroger la durée de l'élément actuel pour être retardé. Le code est le suivant:
public long getdelay (timeunit unit) {return unit.convert (time - maintenant (), timeunit.nanoseconds); }Grâce au constructeur, nous pouvons voir que l'unité du paramètre de temps de retard NS est des nanosecondes. Il est préférable d'utiliser des nanosecondes lors de la conception vous-même, car vous pouvez spécifier n'importe quelle unité lors de l'obtention de la mise. Une fois que les nanosecondes sont utilisées comme unité et que le temps de retard est inférieur aux nanosecondes, il sera gênant. Lorsque vous utilisez, veuillez noter que lorsque l'heure est inférieure à l'heure actuelle, Getdelay renvoie un nombre négatif.
Enfin, nous pouvons utiliser du temps pour spécifier la commande dans la file d'attente, par exemple: laissez le temps de retard le plus long être placé à la fin de la file d'attente.
public int compareto (retardé autre) {if (autre == this) return 0; if (autre instanceof scheduledfutureTask) {ScheduledFutureTask x = (ScheduledFutureTask) autre; Long Diff = temps - x.Time; if (diff <0) return -1; else if (diff> 0) return 1; else if (SequenceNeNumber <x.SencenCenumber) return -1; else return 1; } long d = (getdelay (timeunit.nanoseconds) -other.getdelay (timeunit.nanoseconds)); return (d == 0)? 0: ((d <0)? -1: 1); }Comment mettre en œuvre des files d'attente de blocage retardée
La mise en œuvre des files d'attente de blocage de retard est très simple. Lorsque le consommateur obtient des éléments de la file d'attente, si l'élément n'atteint pas le temps de retard, il bloque le thread actuel.
Long Delay = first.getdelay (timeUtil.nanoseconds); if (delay <= 0) {return q.poll; // Bloquer la file d'attente} else if (leader! = null) {// Lead représente un thread en attendant un message de la file d'attente de blocage disponible.Await (); // Laissez le thread saisir le signal d'attente} else {// Lorsque le leader est nul, définissez le thread actuel sur leadthread thisThread = Thread.currentThread (); essayez le thread {leader = thisthread; // utilisez la méthode Awaitnanos () pour faire en sorte que le thread actuel attende le signal reçu ou attendez le temps de retard) {leader) {Null);} Enfin {If (leader == Thread) {leader = Null; }}}Synchrone
SynchronousQueue est une file d'attente de blocage qui ne stockait pas les éléments. Chaque opération de put doit attendre une opération de prise, sinon les éléments ne peuvent pas être ajoutés. SynchronousQueue peut être considéré comme un passeur, responsable du passage des données traitées par le fil du producteur directement au fil du consommateur. La file d'attente elle-même ne stocke aucun éléments, qui convient très à des scénarios transitifs. Par exemple, les données utilisées dans un thread sont transmises à un autre thread à utiliser. Le débit de la synchrone est supérieur à celui de
LinkedBlockingQueue et ArrayBlockingQueue.
Il prend en charge les files d'attente d'accès équitable. Par défaut, c'est toujours un mécanisme de politique injuste
LinkedRansferqueue
LinkedTransferqueue est une file d'attente de transfert de transfert de blocage non liée composée d'une structure de liste liée. Par rapport aux autres files d'attente de blocage, LinkedTransferqueue a plus de méthodes TryTransfer et de transfert.
Méthode de transfert
Si un consommateur attend actuellement de recevoir un élément (lorsque le consommateur utilise la méthode TAPT () ou la méthode Poll () limitée dans le temps), la méthode de transfert peut immédiatement transférer les éléments passés par le producteur au consommateur. Si aucun consommateur n'attend l'élément de réception, la méthode de transfert stocke l'élément dans le nœud de queue de la file d'attente et attend que l'élément soit consommé par le consommateur avant de revenir.
Méthode TryTransfer
Il est utilisé pour tester si les éléments introduits par le producteur peuvent être directement transmis au consommateur. Si aucun consommateur n'attend l'élément de réception, FALSE est retourné. La différence entre la méthode de transfert est que la méthode Trytransfer revient immédiatement, que le consommateur le reçoive ou non. La méthode de transfert doit attendre que le consommateur le consomme avant de revenir.
Pour la méthode TryTransfer (E E, temps d'attente longue, unité TimeUnit) avec limite de temps, il essaie de passer l'élément passé par le producteur directement au consommateur, mais s'il n'y a pas de consommateur consommant l'élément, il attendra le temps spécifié avant de revenir. Si le délai d'attente n'a pas consommé l'élément, il reviendra faux, et si l'élément est consommé dans le délai d'attente, il reviendra vrai.
LinkedBlockingDeque
LinkedBlockingDeque est une file d'attente de blocage bidirectionnelle composée d'une structure de liste liée. La soi-disant file d'attente bidirectionnelle fait référence au fait que vous pouvez insérer et supprimer des éléments des deux extrémités de la file d'attente. Étant donné que la file d'attente à double extrémité a une entrée supplémentaire à la file d'attente d'opération, la concurrence est réduite de moitié lorsque plusieurs threads rejoignent la file d'attente en même temps. Par rapport aux autres files d'attente de blocage, LinkedBlockingDeque a plus d'addfirst, addlast, offrande, offre, offre, peekfirst, peeklast et autres méthodes. La méthode se termine par le premier mot indique l'insertion, l'acquisition ou la suppression du premier élément de la file d'attente à double extrémité. Une méthode se terminant par le dernier mot, indiquant que le dernier élément de la file d'attente à double extrémité est inséré, obtenu ou supprimé. De plus, la méthode d'insertion ADD est équivalente à AddLast, et la méthode de suppression supprimée est équivalente à la suppression. Cependant, la méthode Take est équivalente à TakeFirst. Je ne sais pas si c'est un bug dans JDK, et il est plus clair d'utiliser la méthode avec les premier et dernier suffixes lors de l'utilisation. La capacité de la file d'attente peut être initialisée lors de l'initialisation de LinkedBlockingDeque pour l'empêcher de gonfler lorsqu'elle est réintégrée. De plus, la file d'attente de blocage bidirectionnelle peut être utilisée dans le mode "vol de travail".
Merci d'avoir lu, j'espère que cela peut vous aider. Merci pour votre soutien à ce site!