CyclicBarrier 源码学习

1、CyclicBarrier 的作用

一种同步辅助,允许一组线程彼此等待到达一个共同的障碍点。cyclicbarrier在包含固定大小的线程的程序中非常有用,这些线程有时必须彼此等待。这个屏障被称为循环,因为它可以在释放等待的线程之后重用。

2、核心结构

// 使用ReentrantLock加锁
private final ReentrantLock lock = new ReentrantLock();
// 锁条件变量,用来处理锁等待,锁唤醒
private final Condition trip = lock.newCondition();
// 初始化等待工作(屏障)的数量
private final int parties;
// 构造函数如果设置Runnable,则会触发Runnable方法
private final Runnable barrierCommand;
// 用于控制屏障的循环使用,如果 generation.token 为true,表示这个屏障已损坏
private Generation generation = new Generation(); 
// 正在等待的工作(屏障)的数量
private int count;

3、两个构造函数

// parties等待工作(屏障)的数量
public CyclicBarrier(int parties) {
    this(parties, null);
}
// parties等待工作(屏障)的数量
// Runnable表示任务会在所有线程到达屏障后执行
public CyclicBarrier(int parties, Runnable barrierAction) {
	if (parties <= 0)
		throw new IllegalArgumentException();
	this.parties = parties;
	this.count = parties;
	this.barrierCommand = barrierAction;
 }

4、等待方法

// 等待直到所有方都调用了这个屏障。
public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}
/**
 * 主要屏障代码,涵盖各种策略。
 * 每当线程执行await,内部变量count--
 * 如果count!=0,自旋在锁条件变量trip上等待
 * 如果count==0,唤醒所有等待线程,如果初始化加载Runnable,那么执行这个方法,并开始
 */
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();
    }
}

5、屏障循环使用

// 更新屏障状态并唤醒所有人。
private void nextGeneration() {
    // 唤醒上一代的所有等待线程
    trip.signalAll();
    // 设置新的控制屏障
    count = parties;
    generation = new Generation();
}

6、实例测试

有一组工作者需要完成一组工作。工作之前需要等待所有工作者全部准备好,准备好以后所有工作者开始工作。

github

/**
 * 
 * CyclicBarrier用法实例
 * 有一组工作者需要完成一组工作。工作之前需要等待所有工作者全部准备好,准备好以后所有工作者开始工作。
 * 
 * @version 1.0
 */
public class CyclicBarrierDriverDemo {

	public static void main(String[] args) {
		Integer N = 5;
		Runnable barrierAction = new Runnable() {
			public void run() {
				System.out.println("工作者全部准备好了,可以开始工作了。");
			}
		};
		
		CyclicBarrier cyclicBarrier = new CyclicBarrier(N, barrierAction);
		for (int i = 0; i < N; i++) {
			new CyclicBarrierWorker(cyclicBarrier, i).start();
		}
	}
	
}

class CyclicBarrierWorker extends Thread {
	CyclicBarrier barrier;
	private Integer i;
	
	public CyclicBarrierWorker(CyclicBarrier barrier, Integer i) {
		this.barrier = barrier;
		this.i = i;
	}
	
	public void run() {
		try {
			Random random = new Random();
			Integer prepare = random.nextInt(1000);
			Thread.sleep(prepare);
			System.out.println("工作者" + i + "准备好了,准备时间 " + prepare + " 毫秒。");
			barrier.await();
			Integer work = random.nextInt(1000);
			Thread.sleep(work);
			System.out.println("工作者" + i + "工作完成,工作时间 " + work + " 毫秒。");
		} catch (Exception e) {

		}
	}
	
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值