展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

CyclicBarrier使用及源码分析

  • 简介
1、允许一组线程相互等待达到一个公共的障碍点,之后再继续执行
2、跟countDownLatch的区别
    CountDownLatch一般用于某个线程等待若干个其他线程执行完任务之后,它才执行;不可重复使用 
    CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;可重用的
  • 案例1
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        // 指定计数器个数
        CyclicBarrier cyclicBarrier = new CyclicBarrier(8);
        // 创建8个线程
        for (int i = 0; i < 8; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    Thread.sleep(finalI * 1000L);
                    System.out.println(Thread.currentThread().getName() + "准备就绪");
                    cyclicBarrier.await();          // 8个线程都准备就绪后
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println("开始比赛");         // 最后8个线程同时进行
            }).start();
        }
    }

}

# 控制台打印结果:
Thread-0准备就绪
Thread-1准备就绪
Thread-2准备就绪
Thread-3准备就绪
Thread-4准备就绪
Thread-5准备就绪
Thread-6准备就绪
Thread-7准备就绪
开始比赛
开始比赛
开始比赛
开始比赛
开始比赛
开始比赛
开始比赛
开始比赛

Process finished with exit code 0
  • 源码分析
# 查看CyclicBarrier对象
    public CyclicBarrier(int parties) {      // 当我们new CyclicBarrier对象时,传入个数
        this(parties, null);
    }

# 查看this方法
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;      // 个数
        this.count = parties;      // 正在等待的个数
        this.barrierCommand = barrierAction;
    }

# 查看count,表示正在等待的个数

# 查看await方法
    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

# 查看dowait方法
    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)
                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();
                }
            }

# 获取broken并指定为false
    private static class Generation {
        Generation() {}                 // prevent access constructor creation
        boolean broken;                 // initially false
    }

# 继续查看dowait方法
    private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;      // 获取锁,并打开锁
        lock.lock();
        try {
            final Generation g = generation;      // 获取broken并指定为false

            if (g.broken)            // 如果为true,则抛出异常
                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();
                }
            }

# 继续查看dowait方法
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      // 如果为0时,执行如下操作
                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 (;;) {                // 否则进入该for循环
                try {
                    if (!timed)        // timed的初始状态为false,!timed则表示true
                        trip.await();        // 则执行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();
        }
    }

# 继续查看dowait方法
    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        // 当等待的线程数量为0时
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    ranAction = true;
                    nextGeneration();        // 执行该方法
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

# 查看nextGeneration方法
    private void nextGeneration() {
        // signal completion of last generation
        trip.signalAll();        // 唤醒所有等待线程
        // set up next generation
        count = parties;
        generation = new Generation();
    }
posted @ 2022-05-16 10:53  DogLeftover  阅读(21)  评论(0编辑  收藏  举报