JUC并发包—CyclicBarrier(循环栅栏)

目录

CyclicBarrier是什么

CyclicBarrier的原理

CyclicBarrier的使用


CyclicBarrier是什么

  • CyclicBarrier是一种同步辅助工具,字面意思就是循环栅栏,它允许一组线程在一个共同的屏障点彼此等待,所有线程到达屏障点后再全部同时执行。
  • 当所有等待线程都被释放以后,CyclicBarrier可以被重用

CyclicBarrier的原理

CyclicBarrier的内部定义了一个ReentrantLock的对象,然后再利用这个ReentrantLock对象生成一个Condition的对象。每当一个线程调用CyclicBarrier的await方法时,首先把剩余屏障的线程数减1,然后判断剩余屏障数是否为0:如果不是,利用Condition的await方法阻塞当前线程;如果是,首先利用Condition的signalAll方法唤醒所有线程,最后重新生成Generation对象以实现屏障的循环使用。

CyclicBarrier的await源码

private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;  //ReentrantLock锁
        lock.lock();
        try {
            final Generation g = generation;

            if (g.broken)
                throw new BrokenBarrierException();

            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }

            int index = --count;             //每次调用await()方法 减1
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    ranAction = true;
                    nextGeneration();        //重新生成Generation()
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

CyclicBarrier的使用

    ExecutorService threadPool = Executors.newFixedThreadPool(5);
        CyclicBarrier barrier = new CyclicBarrier(5,()->{
            System.out.println("游戏结束");
        });

CyclicBarrier的第二个参数可以设置每次使用完后执行的方法,当剩余屏障为0时,会执行该方法,然后执行await()之后的方法,可以用来线程同步

例子

package main.多线程.循环栅栏;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    public static void main(String[] args) {

        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        CyclicBarrier barrier = new CyclicBarrier(5,()->{
                System.out.println("开始下一次循环--------注意该方法调用的时刻");
        });

        threadPool.submit(()->{
            System.out.println("玩家一:加载中");
            try {
                Thread.sleep(5000);
                try {
                    System.out.println("玩家一:加载完成");
                    barrier.await();
                    System.out.println("玩家一:进入游戏");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadPool.submit(()->{
            System.out.println("玩家二:加载中");
            try {
                Thread.sleep(4000);
                try {
                    System.out.println("玩家二:加载完成");
                    barrier.await();
                    System.out.println("玩家二:进入游戏");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadPool.submit(()->{
            System.out.println("玩家三:加载中");
            try {
                Thread.sleep(1500);
                try {
                    System.out.println("玩家三:加载完成");
                    barrier.await();
                    System.out.println("玩家三:进入游戏");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadPool.submit(()->{
            System.out.println("玩家四:加载中");
            try {
                Thread.sleep(7000);
                try {
                    System.out.println("玩家四:加载完成");
                    barrier.await();
                    System.out.println("玩家四:进入游戏");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        threadPool.submit(()->{
            System.out.println("玩家五:加载中");
            try {
                Thread.sleep(10000);
                try {
                    System.out.println("玩家五:加载完成");
                    barrier.await();
                    System.out.println("玩家五:进入游戏");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
----------------------------------------------------------------------------------
        //重复使用CyclicBarrier循环栅栏
        threadPool.submit(()->{
            try {
                Thread.sleep(1000);
                try {
                    System.out.println("玩家五:离开游戏");
                    barrier.await();
                    System.out.println("游戏结束");
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadPool.submit(()->{
            try {
                Thread.sleep(1000);
                try {
                    System.out.println("玩家四:离开游戏");
                    barrier.await();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadPool.submit(()->{
            try {
                Thread.sleep(3000);
                try {
                    System.out.println("玩家三:离开游戏");
                    barrier.await();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadPool.submit(()->{
            try {
                Thread.sleep(4000);
                try {
                    System.out.println("玩家二:离开游戏");
                    barrier.await();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadPool.submit(()->{
            try {
                Thread.sleep(5000);
                try {
                    System.out.println("玩家一:离开游戏");
                    barrier.await();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
}

//结果
玩家一:加载中
玩家二:加载中
玩家三:加载中
玩家四:加载中
玩家五:加载中
玩家三:加载完成
玩家二:加载完成
玩家一:加载完成
玩家四:加载完成
玩家五:加载完成
开始下一次循环--------注意该方法调用的时刻
玩家五:进入游戏
玩家三:进入游戏
玩家二:进入游戏
玩家一:进入游戏
玩家四:进入游戏
玩家五:离开游戏
玩家四:离开游戏
玩家三:离开游戏
玩家二:离开游戏
玩家一:离开游戏
开始下一次循环--------注意该方法调用的时刻
游戏结束

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值