java.util.concurrent.CyclicBarrier同步屏障工具类源码解析

1.CyclicBarrier工具类的特点

CyclicBarrier采用一种屏障的方式来控制线程,让所有线程停在某一点,已到的等最后到才完事。先到的线程将处于阻塞的状态。

2.初识CyclicBarrier

http://blog.csdn.net/ya_1249463314/article/details/52822580


3.CyclicBarrier所属包

package java.util.concurrent;

4.CyclicBarrier的继承与实现关系

public class CyclicBarrier

5.属性

说明:下面所说的线程组是指启动此 barrier 的参与者(所有线程)被叫做线程组。

属性:

/** 定义一个排他锁 */
    private final ReentrantLock lock = new ReentrantLock();
    /** 创建一个等待队列 */
    private final Condition trip = lock.newCondition();
    /** 等待线程的数量 */
    private final int parties;
    /* 当栅栏被释放后执行的线程 */
    private final Runnable barrierCommand;
    /** 当前的一代线程组 */
    private Generation generation = new Generation();

    /**
     * 在当前一代线程组中等待线程的数量从parties减到0。
     * count值是在创建新的一代线程时被重置。
     */
    private int count;
内部类:

 /**
     * 一个栅栏代表了一代线程组,栅栏被重置或者跳闸时,一代线程组发生改变。
     * 如果一代线程组被实例化了,那么这个栅栏被打破的标志位为false。
     */
    private static class Generation {
        boolean broken = false;
    }


6.核心实现

breakBarrier

设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程

/**
     * 设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
     * 在持有锁的时候,才可以调用该方法。
     */
    private void breakBarrier() {
	//设置一代线程组对应的栅栏状态为true(意思就是栅栏被破坏了)
        generation.broken = true;
	//重新设置计数count值
        count = parties;
	//唤醒所有等待的线程
        trip.signalAll();
    }
nextGeneration
重新设置下一代线程组

/**
     * 重新设置下一代线程组
     * 当栅栏跳闸时,就是线程都到达屏障时,就更新同步状态,然后唤醒所有等待的线程。
     * 但是只能在持有锁时才可以调用该方法。
     */
    private void nextGeneration() {
        //唤醒所有等待的线程 
        trip.signalAll();
        //重新设置计数count值
        count = parties;
	//重新创建一代线程组
        generation = new Generation();
    }
doAwait

主要用于限时等待和非限时等待

/**
     * 等待通用方法
     */
    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();
            }
           //获取一代线程组中等待线程的数量-1
           int index = --count;
	   //如果达到跳闸的条件
           if (index == 0) {  // tripped
               boolean ranAction = false;
               try {
	           //获取跳闸后执行的线程
                   final Runnable command = barrierCommand;
		   //如果该线程不为空,那么就执行最后的线程
                   if (command != null)
                       command.run();
		   //将标记位设置为true
                   ranAction = true;
		   //重新设置下一代线程组
                   nextGeneration();
                   return 0;
               } finally {
                   if (!ranAction)
                       breakBarrier();
               }
           }

            // 死循环,除非出现栅栏破坏了、线程中断、超时情况才结束循环
            for (;;) {
                try {
		    /* timed时间标志位
		     * 如果timed为false,那么线程等待队列将一直被挂起,线程一直处于等待状态。
		     */
                    if (!timed)
                        trip.await();
                    else if (nanos > 0L)
		    /**
		     * 如果时间标志位timed为true
		     * 如果等待时间大于0L,那么将线程等待队列在指定时间到达前将等待
		     */
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
		    //如果当前这一代线程组对应的栅栏状态未破坏
                    if (g == generation && ! g.broken) {
			//设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
                        breakBarrier();
			//抛出中断异常
                        throw ie;
                    } else {
			/* 如果线程没有结束等待甚至根本没有中断,那么这个中断操作将会随后在执行。
			 *
			 */
                        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();
        }
    }

7.构造方法

/**
     * 栅栏构造器
     * 输入参数为线程组中的等待线程数、最后执行的线程
     */
    public CyclicBarrier(int parties, Runnable barrierAction) {
	//如果等待线程数不大于0,那么就抛出非法参数异常
        if (parties <= 0) throw new IllegalArgumentException();
	//初始化等待线程数
        this.parties = parties;
	//初始化操作线程数
        this.count = parties;
	//初始化栅栏破坏后,最后执行的线程
        this.barrierCommand = barrierAction;
    }

    /**
     * 栅栏构造器
     * 就是没有最后执行的线程的栅栏
     */
    public CyclicBarrier(int parties) {
        this(parties, null);
    }

8.方法

/**
     * 获取启动此 barrier 的参与者数目
     */
    public int getParties() {
        return parties;
    }

    /**
     * 在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
     */
    public int await(long timeout, TimeUnit unit)
        throws InterruptedException,
               BrokenBarrierException,
               TimeoutException {
        return dowait(true, unit.toNanos(timeout));
    }

    /**
     * 查看屏障是否处于破坏状态
     */
    public boolean isBroken() {
	//获取当前的排它锁
        final ReentrantLock lock = this.lock;
	//获取锁
        lock.lock();
        try {
	    //返回当前这一代线程组中的状态
            return generation.broken;
        } finally {
	    //释放锁
            lock.unlock();
        }
    }

    /**
     * 将屏障设置为初始化的状态
     */
    public void reset() {
	//获取排他锁
        final ReentrantLock lock = this.lock;
	//获取锁
        lock.lock();
        try {
	    //设置当前的栅栏已经被破坏(说明线程都到达了同一点)并且唤醒所有线程
            breakBarrier(); 
	    //重新设置下一代线程组
            nextGeneration(); 
        } finally {
	    //释放锁
            lock.unlock();
        }
    }

    /**
     * 获取当前屏障处等待的线程数
     */
    public int getNumberWaiting() {
	//获取排他锁
        final ReentrantLock lock = this.lock;
	//获取锁
        lock.lock();
        try {
	    //总等待线程数减去当前剩余没到达的线程数
            return parties - count;
        } finally {
	    //释放锁
            lock.unlock();
        }
    }



--------------------------------------------jdk1.7



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值