Maison >Java >javaDidacticiel >Analyse du code source CyclicBarrier en Java
Pour CountDownLatch
, d'autres fils de discussion sont des joueurs de jeu, comme League of Legends, et le le fil principal est contrôle Le fil où le jeu commence. Avant que tous les joueurs ne soient prêts, le fil principal est en attente, ce qui signifie que le jeu ne peut pas démarrer. Lorsque tous les joueurs sont prêts, l'exécuteur d'action suivant est le fil conducteur qui démarre la partie.
Pour CyclicBarrier, supposons qu'une entreprise souhaite que tous les employés mènent une activité de consolidation d'équipe. L'activité consiste à franchir trois obstacles. Le temps nécessaire à chaque personne pour franchir les obstacles est différent. Cependant, l’entreprise exige que chacun franchisse l’obstacle actuel avant de commencer à franchir l’obstacle suivant. Autrement dit, une fois que tout le monde a franchi le premier obstacle, il commence à franchir le deuxième obstacle, et ainsi de suite. De manière analogique, chaque employé est un « autre fil conducteur ». Le programme se termine lorsque tout le monde a surmonté tous les obstacles. Le fil de discussion principal est peut-être terminé depuis longtemps, nous n'avons donc pas à nous soucier du fil de discussion principal ici.
CyclicBarrier ne montre pas de quelle classe parent il hérite ni de quelle interface parent il implémente, tous les AQS et verrous réentrants Pas par héritage, mais par composition.
public class CyclicBarrier {} ``` ### 类的内部类 CyclicBarrier类存在一个内部类Generation,每一次使用的CycBarrier可以当成Generation的实例,其源代码如下 ```java private static class Generation { boolean broken = false; }
Description : La classe Generation a un attribut cassé, qui est utilisé pour indiquer si la barrière actuelle est endommagée.
public class CyclicBarrier { /** The lock for guarding barrier entry */ // 可重入锁 private final ReentrantLock lock = new ReentrantLock(); /** Condition to wait on until tripped */ // 条件队列 private final Condition trip = lock.newCondition(); /** The number of parties */ // 参与的线程数量 private final int parties; /* The command to run when tripped */ // 由最后一个进入 barrier 的线程执行的操作 private final Runnable barrierCommand; /** The current generation */ // 当前代 private Generation generation = new Generation(); // 正在等待进入屏障的线程数量 private int count; }
Description : Cet attribut a un objet ReentrantLock et un objet Condition, et l'objet Condition est basé sur AQS, donc en dernière analyse, la couche inférieure est toujours prise en charge par AQS.
Constructeur de type CyclicBarrier(int, Runnable)
public CyclicBarrier(int parties, Runnable barrierAction) { // 参与的线程数量小于等于0,抛出异常 if (parties <= 0) throw new IllegalArgumentException(); // 设置parties this.parties = parties; // 设置count this.count = parties; // 设置barrierCommand this.barrierCommand = barrierAction; }
#🎜🎜 #Description : Ce constructeur peut spécifier le nombre de threads associés au CyclicBarrier et peut spécifier l'action d'exécution une fois que tous les threads entrent dans la barrière. L'action d'exécution est déterminée par le dernier thread qui exécute la barrière. . mettre en œuvre.
Constructeur de type CyclicBarrier(int)
public CyclicBarrier(int parties) { // 调用含有两个参数的构造函数 this(parties, null); }
Fonction principale - fonction dowaitCette fonction est la fonction principale de la classe CyclicBarrier. La fonction d'attente fournie par la classe CyclicBarrier est appelée fonction doawait at. la couche inférieure,Description : Ceci Le constructeur exécute uniquement le nombre de threads associés au CyclicBarrier et ne définit pas d'actions d'exécution.
Le code source est le suivant :
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { // 保存当前锁 final ReentrantLock lock = this.lock; // 锁定 lock.lock(); try { // 保存当前代 final Generation g = generation; if (g.broken) // 屏障被破坏,抛出异常 throw new BrokenBarrierException(); if (Thread.interrupted()) { // 线程被中断 // 损坏当前屏障,并且唤醒所有的线程,只有拥有锁的时候才会调用 breakBarrier(); // 抛出异常 throw new InterruptedException(); } // 减少正在等待进入屏障的线程数量 int index = --count; if (index == 0) { // 正在等待进入屏障的线程数量为0,所有线程都已经进入 // 运行的动作标识 boolean ranAction = false; try { // 保存运行动作 final Runnable command = barrierCommand; if (command != null) // 动作不为空 // 运行 command.run(); // 设置ranAction状态 ranAction = true; // 进入下一代 nextGeneration(); return 0; } finally { if (!ranAction) // 没有运行的动作 // 损坏当前屏障 breakBarrier(); } } // loop until tripped, broken, interrupted, or timed out // 无限循环 for (;;) { try { if (!timed) // 没有设置等待时间 // 等待 trip.await(); else if (nanos > 0L) // 设置了等待时间,并且等待时间大于0 // 等待指定时长 nanos = trip.awaitNanos(nanos); } catch (InterruptedException ie) { if (g == generation && ! g.broken) { // 等于当前代并且屏障没有被损坏 // 损坏当前屏障 breakBarrier(); // 抛出异常 throw ie; } else { // 不等于当前带后者是屏障被损坏 // We're about to finish waiting even if we had not // been interrupted, so this interrupt is deemed to // "belong" to subsequent execution. // 中断当前线程 Thread.currentThread().interrupt(); } } if (g.broken) // 屏障被损坏,抛出异常 throw new BrokenBarrierException(); if (g != generation) // 不等于当前代 // 返回索引 return index; if (timed && nanos <= 0L) { // 设置了等待时间,并且等待时间小于0 // 损坏屏障 breakBarrier(); // 抛出异常 throw new TimeoutException(); } } } finally { // 释放锁 lock.unlock(); } }Fonction Core - fonction nextGeneration Cette fonction entre dans tous les threads Elle sera appelée après la barrière, c'est-à-dire que la version suivante est générée et tous les threads peuvent réintégrer la barrière
Le code source est comme. suit :
private void nextGeneration() { // signal completion of last generation // 唤醒所有线程 trip.signalAll(); // set up next generation // 恢复正在等待进入屏障的线程数量 count = parties; // 新生一代 generation = new Generation(); }#🎜 🎜#Dans cette fonction, la méthode signalAll d'AQS est appelée, ce qui réveille tous les threads en attente. Si tous les threads attendent cette condition, réveillez tous les threads. Le code source est le suivant :
public final void signalAll() {
if (!isHeldExclusively()) // 不被当前线程独占,抛出异常
throw new IllegalMonitorStateException();
// 保存condition队列头节点
Node first = firstWaiter;
if (first != null) // 头节点不为空
// 唤醒所有等待线程
doSignalAll(first);
}
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!