CyclicBarrier源码解读,若要转载请注明出处

/*
 * CyclicBarrier源码解读,若要转载,请注明出处!
 */

package java.util.concurrent;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * @author 赵泉伟
 */
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;//可选的需执行的Runnable对象
    /** The current generation */
    private Generation generation = new Generation();//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() {//创建Generation对象
        // signal completion of last generation
        trip.signalAll();//唤醒所有线程
        // set up next generation
        count = parties;//重置计数器,默认为原始线程总数
        generation = new Generation();//创建Generation对象
    }

    /**
     * Sets current barrier generation as broken and wakes up everyone.
     * Called only while holding lock.
     */
    private void breakBarrier() {//破损模式
        generation.broken = true;//置为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;//获取Generation对象

            if (g.broken)//如果破损状态是true
                throw new BrokenBarrierException();//则抛异常

            if (Thread.interrupted()) {//如果当前线程被中断过
                breakBarrier();//调用破损模式方法
                throw new InterruptedException();//并抛异常
            }

            int index = --count;//计数器自减
            if (index == 0) {  // 如果计数器为0表示是最后一个线程
                boolean ranAction = false;//Bool类型的标志位
                try {
                    final Runnable command = barrierCommand;//获取构造器传入的Runnable对象
                    if (command != null)//如果对象不是空
                        command.run();//则调用run方法执行
                    ranAction = true;//置为true
                    nextGeneration();//重置计数器并唤醒所有线程
                    return 0;//返回0
                } finally {
                    if (!ranAction)//如果发生了异常则标志位为false
                        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) {//如果是当前的generation对象并且没有破损
                        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)//如果generation不是当前的generation对象
                    return index;//则返回当前的索引值

                if (timed && nanos <= 0L) {//如果是超时模式但是超时时间<=0
                    breakBarrier();//则调用破损模式
                    throw new TimeoutException();//抛出超时异常
                }
            }
        } finally {
            lock.unlock();//始终要解锁
        }
    }

    /**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and which
     * will execute the given barrier action when the barrier is tripped,
     * performed by the last thread entering the barrier.
     *
     * @param parties the number of threads that must invoke {@link #await}
     *        before the barrier is tripped
     * @param barrierAction the command to execute when the barrier is
     *        tripped, or {@code null} if there is no action
     * @throws IllegalArgumentException if {@code parties} is less than 1
     */
    public CyclicBarrier(int parties, Runnable barrierAction) {//带原始线程数量和Runnable对象的构造器
        if (parties <= 0) throw new IllegalArgumentException();//如果线程数量<=0则抛出异常
        this.parties = parties;//为parties赋值
        this.count = parties;//计数器count默认为parties
        this.barrierCommand = barrierAction;//为Runnable对象赋值
    }

    /**
     * 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
     */
    public CyclicBarrier(int parties) {//带原始线程数量的构造器
        this(parties, null);//调用构造器初始化
    }

    /**
     * Returns the number of parties required to trip this barrier.
     *
     * @return 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.
     *
     * <p>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:
     * <ul>
     * <li>The last thread arrives; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * one of the other waiting threads; or
     * <li>Some other thread times out while waiting for barrier; or
     * <li>Some other thread invokes {@link #reset} on this barrier.
     * </ul>
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * <p>If the barrier is {@link #reset} while any thread is waiting,
     * or if the barrier {@linkplain #isBroken is broken} when
     * {@code await} is invoked, or while any thread is waiting, then
     * {@link BrokenBarrierException} is thrown.
     *
     * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
     * then all other waiting threads will throw
     * {@link BrokenBarrierException} and the barrier is placed in the broken
     * state.
     *
     * <p>If the current thread is the last thread to arrive, and a
     * non-null barrier action was supplied in the constructor, then the
     * current thread runs the action before allowing the other threads to
     * continue.
     * If an exception occurs during the barrier action then that exception
     * will be propagated in the current thread and the barrier is placed in
     * the broken state.
     *
     * @return the arrival index of the current thread, where index
     *         {@code getParties() - 1} indicates the first
     *         to arrive and zero indicates the last to arrive
     * @throws InterruptedException if the current thread was interrupted
     *         while waiting
     * @throws BrokenBarrierException if <em>another</em> thread was
     *         interrupted or timed out while the current thread was
     *         waiting, or the barrier was reset, or the barrier was
     *         broken when {@code await} was called, or the barrier
     *         action (if present) failed due to an exception
     */
    public int await() throws InterruptedException, BrokenBarrierException {//阻塞方法
        try {
            return dowait(false, 0L);//调用阻塞方法 ,超时默认默认为false,超时时间默认为0
        } catch (TimeoutException toe) {//捕捉超时异常
            throw new Error(toe); // 抛出Error类型异常
        }
    }

    /**
     * Waits until all {@linkplain #getParties parties} have invoked
     * {@code await} on this barrier, or the specified waiting time elapses.
     *
     * <p>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:
     * <ul>
     * <li>The last thread arrives; or
     * <li>The specified timeout elapses; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * the current thread; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
     * one of the other waiting threads; or
     * <li>Some other thread times out while waiting for barrier; or
     * <li>Some other thread invokes {@link #reset} on this barrier.
     * </ul>
     *
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     *
     * <p>If the specified waiting time elapses then {@link TimeoutException}
     * is thrown. If the time is less than or equal to zero, the
     * method will not wait at all.
     *
     * <p>If the barrier is {@link #reset} while any thread is waiting,
     * or if the barrier {@linkplain #isBroken is broken} when
     * {@code await} is invoked, or while any thread is waiting, then
     * {@link BrokenBarrierException} is thrown.
     *
     * <p>If any thread is {@linkplain Thread#interrupt interrupted} while
     * waiting, then all other waiting threads will throw {@link
     * BrokenBarrierException} and the barrier is placed in the broken
     * state.
     *
     * <p>If the current thread is the last thread to arrive, and a
     * non-null barrier action was supplied in the constructor, then the
     * current thread runs the action before allowing the other threads to
     * continue.
     * If an exception occurs during the barrier action then that exception
     * will be propagated in the current thread and the barrier is placed in
     * the broken state.
     *
     * @param timeout the time to wait for the barrier
     * @param unit the time unit of the timeout parameter
     * @return the arrival index of the current thread, where index
     *         {@code getParties() - 1} indicates the first
     *         to arrive and zero indicates the last to arrive
     * @throws InterruptedException if the current thread was interrupted
     *         while waiting
     * @throws TimeoutException if the specified timeout elapses.
     *         In this case the barrier will be broken.
     * @throws BrokenBarrierException if <em>another</em> thread was
     *         interrupted or timed out while the current thread was
     *         waiting, or the barrier was reset, or the barrier was broken
     *         when {@code await} was called, or the barrier action (if
     *         present) failed due to an exception
     */
    public int await(long timeout, TimeUnit unit)//带超时时间的阻塞
            throws InterruptedException,
            BrokenBarrierException,
            TimeoutException {
        return dowait(true, unit.toNanos(timeout));//调用阻塞方法,超时状态为true,传入对应的超时时间
    }

    /**
     * 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();   // 调用破损模式方法
            nextGeneration(); // 调用重置方法并且创建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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值