Für CountDownLatch
sind andere Threads Spieler wie League of Legends, und der Hauptthread ist der Thread, der den Start des Spiels steuert. Bevor alle Spieler bereit sind, befindet sich der Hauptthread im Wartezustand, was bedeutet, dass das Spiel nicht starten kann. Wenn alle Spieler bereit sind, ist der nächste Aktionsausführer der Hauptthread, der das Spiel startet.
Angenommen, ein Unternehmen möchte, dass alle Mitarbeiter eine Teambuilding-Aktivität durchführen. Der Inhalt der Aktivität besteht darin, drei Hindernisse zu überwinden. Das Unternehmen verlangt jedoch, dass jeder über das aktuelle Hindernis klettert, bevor er mit dem Klettern über das nächste Hindernis beginnt. Das heißt, nachdem jeder über das erste Hindernis geklettert ist, beginnt er mit dem Klettern über das zweite Hindernis und so weiter. Analog ist jeder Mitarbeiter ein „anderer Thread“. Das Programm endet, wenn alle Hindernisse überwunden sind. Der Hauptthread ist möglicherweise schon vor langer Zeit zu Ende, sodass wir uns hier nicht um den Hauptthread kümmern müssen.
CyclicBarrier zeigt nicht an, welche übergeordnete Klasse es erbt oder welche übergeordnete Schnittstelle es implementiert. Alle AQS- und Wiedereintrittssperren werden nicht durch Vererbung, sondern durch Kombination implementiert.
public class CyclicBarrier {} ``` ### 类的内部类 CyclicBarrier类存在一个内部类Generation,每一次使用的CycBarrier可以当成Generation的实例,其源代码如下 ```java private static class Generation { boolean broken = false; }
Erläuterung: Die Generation-Klasse verfügt über ein Attribut „gebrochen“, das verwendet wird, um anzuzeigen, ob die aktuelle Barriere beschädigt ist.
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; }
Erklärung: Dieses Attribut verfügt über ein ReentrantLock-Objekt und ein Condition-Objekt, und das Condition-Objekt basiert auf AQS, sodass die unterste Ebene letztendlich immer noch von AQS unterstützt wird.
CyclicBarrier(int, Runnable)-Typkonstruktor
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; }
Beschreibung: Dieser Konstruktor kann die Anzahl der Threads angeben, die dem CyclicBarrier zugeordnet sind, und zwar, nachdem alle Threads die Barriere betreten haben Die Ausführungsaktion wird vom letzten Thread ausgeführt, der die Barriere ausführt.
CyclicBarrier(int)-Typkonstruktor
public CyclicBarrier(int parties) { // 调用含有两个参数的构造函数 this(parties, null); }
Beschreibung: Dieser Konstruktor führt nur die Anzahl der Threads aus, die mit dem CyclicBarrier verknüpft sind, und legt nicht die Ausführungsaktion fest.
Diese Funktion ist die Kernfunktion der CyclicBarrier-Klasse. Die von der CyclicBarrier-Klasse bereitgestellte Wait-Funktion ruft die Doawat-Funktion auf der untersten Ebene auf.
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(); } }
Der Quellcode lautet wie folgt:
private void nextGeneration() { // signal completion of last generation // 唤醒所有线程 trip.signalAll(); // set up next generation // 恢复正在等待进入屏障的线程数量 count = parties; // 新生一代 generation = new Generation(); }
Der Quellcode lautet wie folgt:
public final void signalAll() { if (!isHeldExclusively()) // 不被当前线程独占,抛出异常 throw new IllegalMonitorStateException(); // 保存condition队列头节点 Node first = firstWaiter; if (first != null) // 头节点不为空 // 唤醒所有等待线程 doSignalAll(first); }
Das obige ist der detaillierte Inhalt vonCyclicBarrier-Quellcode-Analyse in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!