CyclicBarrier

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


public class CyclicBarrier {
   
    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();
    //总线程数
    private final int parties;
    //栅栏方法
    private final Runnable barrierCommand;
    //每次运行栅栏方法后会重新创建下一个轮回类Generation
	//此对象属于标识类,没有效方法
    private Generation generation = new Generation();

    /**每个轮回的计数器从parties到0递减,每个轮回有线程调用await时count减1
	 *直到0时调用栅栏方法并创建下一个轮回
	 *创建下一个轮回(调用nextGeneration)或终止(调用breakBarrier)CyclicBarrier是count被重置为parties的值
     */
    private int count;

    /**
     * 运行栅栏方法后唤醒条件队列中的所有线程,重置计数器,并创建下一个轮回,
	 * 条件队列中所有被唤醒的线程会转存到等待队列中,只有一个线程可以获得锁运行,
	 * 其它线程会继续挂起,直到有锁释放
     */
    private void nextGeneration() {
        //代表上一个轮回完成
        trip.signalAll();
        // 并设置下一个轮回
        count = parties;
        generation = new Generation();
    }

    /**终止CyclicBarrier并唤醒所有条件队列的线程,此方法在持有锁的时候调用,
     * 可由isBroken()方法返回
     */
    private void breakBarrier() {
        generation.broken = true;
        count = parties;
        trip.signalAll();
    }

    /**
     * 等待会唤醒的核心方法
     */
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        lock.lock();//必须持有锁
        try {
			//此刻将全局的generation保存到本地(generation在其它线程运行到栅栏处时会重新创建)
            final Generation g = generation;
			//一旦终止了cyclicBarrier就不允许再调用
			//终止一般是因为其中一个线程被中断,或者运行栅栏方法时抛异常
            if (g.broken)
                throw new BrokenBarrierException();

            if (Thread.interrupted()) {
				//只要有一个线程被中断,那么最终会终止cyclicBarrier并唤醒所有线程
                breakBarrier();
				//当前线程抛出中断异常
                throw new InterruptedException();
            }
			//等待计数器清零后执行栅栏方法
            int index = --count;
			//index为0代表是最后一个执行await的线程
			//执行栅栏方法然后唤醒所有线程继续执行
            if (index == 0) {  
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();//如果抛异常会执行breakBarrier进行终止
                    ranAction = true;//run方法正常执行,创建下一个轮回
                    nextGeneration();
                    return 0;//当前线程返回并释放锁后其余线程得以获取锁运行
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

            // 循环直到 栅栏, broken终止, 线程中断, 或等待超时
            for (;;) {
                try {
                    if (!timed)
						//不超时直接调用await挂起当前线程,并释放持有的锁
                        trip.await();
                    else if (nanos > 0L)
						//调用超时的方法
                        nanos = trip.awaitNanos(nanos);
						//注:只有在signal之前中断才会抛此异常,如果在signal之后也就是运行栅栏方法后中断
						//是不会抛异常的,只是线程标识为中断,当再次对此线程运行dowait时会终止cyclicBarrier
						//并抛中断异常(参见此方法上文)
                } catch (InterruptedException ie) {
					//当前线程被中断且还没有运行到栅栏处,那么终止cyclicBarrier
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        //g 不等于 generation
                        //当前线程被中断,从条件队列转移到等待队列,而继续挂起
						//当再次获取到锁时,在await方法中抛中断异常进入到这里发现栅栏方法已执行,
						//generation对象被更新,那么设置当前线程的中断标识下次再调用此线程的await时会
						//终止cyclicBarrier
                        Thread.currentThread().interrupt();
                    }
                }
				//已经终止抛异常
                if (g.broken)
                    throw new BrokenBarrierException();
				//当前线程因最后一个线程到达栅栏而被唤醒,此时全局的generation是
				//全新对象与g不等
                if (g != generation)
                    return index;
				//当前线程因为等待超时,且还没有运行到栅栏方法,那么终止cyclicBarrier
                if (timed && nanos <= 0L) {
                    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) {
        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
     */
    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;
    }

  
    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();
        }
    }

    /**
     * 重置CyclicBarrier以便可以循环利用
     */
    public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
			//终止当前轮回并唤醒条件队列的所有线程
            breakBarrier();   // break the current generation
			//创建新的轮回
            nextGeneration(); // start a new generation
        } finally {
            lock.unlock();
        }
    }

    /**
     * 返回等待的线程数
     */
    public int getNumberWaiting() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return parties - count;
        } finally {
            lock.unlock();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值