CyclicBarrier源码分析
来源:互联网 发布:纪元2070优化 编辑:程序博客网 时间:2024/05/16 09:54
package java.util.concurrent;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;public class CyclicBarrier { /** * Each use of the barrier is represented as a generation instance. * The generation changes whenever the barrier is tripped, or * is reset. There can be many generations associated with threads * using the barrier - due to the non-deterministic way the lock * may be allocated to waiting threads - but only one of these * can be active at a time (the one to which {@code count} applies) * and all the rest are either broken or tripped. * There need not be an active generation if there has been a break * but no subsequent reset. */ private static class Generation { boolean broken = false; } /** 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 */ private final Runnable barrierCommand; /** The current generation */ private Generation generation = new Generation(); /** * Number of parties still waiting. Counts down from parties to 0 on each generation. * It is reset to parties on each new generation or when broken. */// 计数器 private int count; /** * Updates state on barrier trip and wakes up everyone. * Called only while holding lock. */ private void nextGeneration() { // signal completion of last generation trip.signalAll(); // set up next generation count = parties; generation = new Generation(); } /** * Sets current barrier generation as broken and wakes up everyone. * Called only while holding lock. */ private void breakBarrier() { generation.broken = true; count = parties; trip.signalAll(); } /** * Main barrier code, covering the various policies. */ 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) { // tripped boolean ranAction = false; try { final Runnable command = barrierCommand; if (command != null) command.run(); 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) 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) { breakBarrier(); throw new TimeoutException(); } } } finally { lock.unlock(); } }// 当所有线程都到达屏障时,优先执行barrierAction这个线程。注意:barrierAction可以不在“所有线程”之中。 public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; } /** * Creates a new {@code CyclicBarrier} that will trip when the given number of parties (threads) are waiting upon it, * and does not perform a predefined action when the barrier is tripped. * * @param parties the number of threads that must invoke {@link #await} before the barrier is tripped * @throws IllegalArgumentException if {@code parties} is less than 1 */// 构造一个拦截线程数量为parties的屏障 public CyclicBarrier(int parties) { this(parties, null); } /** * Returns the number of parties required to trip this barrier. */ public int getParties() { return parties; } /** * Waits until all {@linkplain #getParties parties} have invoked * {@code await} on this barrier. * * If the current thread is not the last to arrive then it is disabled for thread scheduling purposes * and lies dormant until one of the following things happens: * The last thread arrives; * Some other thread {@linkplain Thread#interrupt interrupts} the current thread; * Some other thread {@linkplain Thread#interrupt interrupts} one of the other waiting threads; * Some other thread times out while waiting for barrier; * Some other thread invokes {@link #reset} on this barrier. * * 线程调用await方法告诉CyclicBarrier:(线程)已经到达了屏障,然后当前线程被阻塞 */ public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } } public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException { return dowait(true, unit.toNanos(timeout)); } /** * Queries if this barrier is in a broken state. * * @return {@code true} if one or more parties broke out of this * barrier due to interruption or timeout since * construction or the last reset, or a barrier action * failed due to an exception; {@code false} otherwise. */ public boolean isBroken() { final ReentrantLock lock = this.lock; lock.lock(); try { return generation.broken; } finally { lock.unlock(); } } /** * Resets the barrier to its initial state. If any parties are * currently waiting at the barrier, they will return with a * {@link BrokenBarrierException}. Note that resets <em>after</em> * a breakage has occurred for other reasons can be complicated to * carry out; threads need to re-synchronize in some other way, * and choose one to perform the reset. It may be preferable to * instead create a new barrier for subsequent use. */ public void reset() { final ReentrantLock lock = this.lock; lock.lock(); try { breakBarrier(); // break the current generation nextGeneration(); // start a new generation } finally { lock.unlock(); } } /** * Returns the number of parties currently waiting at the barrier. * This method is primarily useful for debugging and assertions. * * @return the number of parties currently blocked in {@link #await} */ public int getNumberWaiting() { final ReentrantLock lock = this.lock; lock.lock(); try { return parties - count; } finally { lock.unlock(); } }}
阅读全文
0 0
- 源码分析-CyclicBarrier
- CyclicBarrier源码分析
- Java 并发 --- CyclicBarrier源码分析
- JUC源码分析12-locks-CyclicBarrier
- 《Java源码分析》:CyclicBarrier(part one)
- 《Java源码分析》:CyclicBarrier(part two)
- 【Java8源码分析】并发包-CyclicBarrier
- Java多线程 -- JUC包源码分析11 -- CyclicBarrier源码分析
- CyclicBarrier源码
- jdk 源码分析(16)java CyclicBarrier 源码解析
- Java多线程系列(八)—CyclicBarrier源码分析
- 深度解析CyclicBarrier源码
- CyclicBarrier 源码阅读
- CyclicBarrier源码浅析
- CyclicBarrier分析与实例
- CountDownLatch & CyclicBarrier源码实现解析
- cyclicBarrier
- CyclicBarrier
- 逗号表达式
- C++plus笔记7
- 如何将自己应用替换tomcat自带应用
- LightOJ
- 相关接口
- CyclicBarrier源码分析
- jQuery实战学习之点击显示和隐藏
- JAVA 函数 随机生成经纬度
- Javaweb零基础开发(一) Struts配置
- 11、视图的转发forward(forward)和重定向(redirect)
- ThreadPoolExecutor源码分析
- Leetcode 第九题:最长回文子字符串
- JavaScript 鼠标事件
- day10--自我反省