J'ai effectivement pris le temps d'étudier la source, par pure curiosité, et l'idée derrière cela est assez simple. La version la plus récente au moment de la rédaction de ce post est 3.2.1.
Il y a un tampon de stockage de pré-alloués événements qui va contenir les données pour les consommateurs à lire.
Le tampon est soutenu par un ensemble d'indicateurs (tableau d'entiers) de sa longueur qui décrit la disponibilité de la mémoire tampon de fentes (voir plus loin pour les détails). Le tableau est accessible comme une java#AtomicIntegerArray, donc, pour les fins de la présente explenation on peut tout aussi bien supposer qu'il soit.
Il peut être n'importe quel nombre de producteurs. Lorsque le producteur veut écrire dans la mémoire tampon, un long numéro est généré (comme dans l'appel de AtomicLong#getAndIncrement, le Perturbateur utilise sa propre mise en œuvre, mais il fonctionne de la même manière). Appelons cela a généré un long producerCallId. De manière similaire, un consumerCallId est généré lorsqu'un consommateur se TERMINE la lecture d'un logement à partir d'un tampon. La plus récente consumerCallId est accessible.
(Si il y a beaucoup de consommateurs, l'appel avec le plus petit id est choisie.)
Ces identifiants sont ensuite comparés, et si la différence entre les deux est moindre que le tampon de côté, le producteur est autorisé à écrire.
(Si le producerCallId est plus grande que la récente consumerCallId + bufferSize, cela signifie que la mémoire est pleine, et le producteur est obligé de bus-attendre jusqu'à ce qu'une place devient disponible.)
Le producteur est ensuite affecté à l'emplacement dans la mémoire tampon en fonction de son callId (qui est prducerCallId modulo bufferSize, mais depuis le bufferSize est toujours une puissance de 2 (limite appliquée sur le tampon de la création), le actuall fonctionnement utilisé est producerCallId & (bufferSize - 1)). Il est ensuite libre de les modifier le cas dans cet emplacement.
(L'algorithme est un peu plus compliqué, impliquant la mise en cache récente consumerId dans un autre atomique de référence pour l'optimisation).
Lorsque l'événement a été modifié, le changement est "publié". Lors de la publication de la fente respective dans le drapeau de tableau est rempli avec la mise à jour du drapeau. La valeur de l'indicateur est le nombre de la boucle (producerCallId divisé par la taille de tampon (nouveau depuis bufferSize est une puissance de 2, le fonctionnement réel est un décalage à droite).
De manière similaire, il peut être n'importe quel nombre de consommateurs. Chaque fois qu'un consommateur qui souhaite accéder à la mémoire tampon, une consumerCallId est généré (en fonction de la façon dont les consommateurs ont été ajoutés à la perturbateur atomiques utilisés dans la génération d'identifiants peuvent être partagées ou distincte pour chacun d'eux). Cette consumerCallId est ensuite comparée à la plus récente producentCallId, et si c'est le moindre des deux, le lecteur est autorisé à passer.
(De même, si le producerCallId est de même pour la consumerCallId, cela signifie que la mémoire tampon est empety et le consommateur est obligé d'attendre. La manière d'attente est défini par un WaitStrategy pendant perturbateur de la création.)
Pour les consommateurs individuels (ceux avec leurs propres id generator), la prochaine chose à vérifier la capacité de lot de consommer. Les fentes dans la mémoire tampon sont examinées dans l'ordre de l'un respectif de la consumerCallId (l'indice est déterminé de la même manière que pour les producteurs), à l'un respectif de la récente producerCallId.
Ils sont examinés dans une boucle, en comparant la valeur de l'indicateur écrit dans le drapeau de tableau, à l'encontre d'un indicateur de la valeur générée pour la consumerCallId. Si les indicateurs de match cela signifie que les producteurs de remplissage des fentes a commis leurs modifications. Si non, la boucle est cassé, et le plus engagé changeId est retourné. Les fentes de ConsumerCallId à reçu en changeId peut être consommé dans le lot.
Si un groupe de consommateurs lisez ensemble (celles qui ont partagé id generator), chacun ne prend qu'un seul callId, et seule la fente pour que seul callId est vérifié et retourné.