CyclicBarrier

CyclicBarrier【循环栅栏】

循环栅栏,类似倒计数器,也是用来阻塞线程,不过它的重点在于循环使用

而倒计数器只能用一次(这属于他们之间最明显的一个区别)

下面我们看几个循环栅栏 CyclicBarrier 内部的方法:

构造方法public CyclicBarrier(int parties, Runnable barrierAction),第一个表示需等待(阻塞)的线程数,第二个barrierAction就是上面我们说的栅栏动作,即当最后一个线程也被阻塞时,就会触发这个栅栏动作(这个参数可选,如果没有,则不执行任何动作)
等待public int await(),阻塞当前线程,直到最后一个线程被阻塞,才会恢复
超时等待public boolean await(long timeout, TimeUnit unit),类似上面的await,只不过可以设置超时时间
获取当前等待的线程数public int getNumberWaiting(),即调用了await方法的线程数量

场景:

大事化小,小事合并:就是将某个大任务拆解为多个小任务,等到小任务都完成,再合并为一个结果

多人对战游戏团战

上面的倒计数器表示游戏开始前的准备工作(只需准备一次)
而这里的循环栅栏则可以表示游戏开始后的团战工作(可团战多次)
 
 

下面看下例子:多人游戏团战画面

public class CyclicBarrierDemo {
    public static void main(String[] args) throws InterruptedException {

        // 1. 创建一个循环栅栏,给定等待线程数10和栅栏动作
        CyclicBarrier barrier = new CyclicBarrier(10,()->{
            // 栅栏动作,等到所有线程都await,就会触发
            System.out.println("=== 人齐了,开始团吧");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("=== 准备第一波团战 ===");
        // 2. 创建10个线程,模拟10个玩家
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    // 玩家到场
                    System.out.println(Thread.currentThread().getName()+"=>第一波团,我准备好了");
                    // 等待其他人,等人齐就可以团了(人齐了会执行栅栏动作,此时这边也会恢复执行)
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        // 3. 查询当前等待都线程数量,如果不为0,则主线程继续等待
        while (barrier.getNumberWaiting()!=0){
            Thread.sleep(1000);
        }
        System.out.println("=== 第一波团战结束 ===");
        
        // 4. 此时还可以进行第二波第三波团战。。。(循环栅栏可循环触发,倒计数器只能触发一次)
        
    }
}

输出如下:

=== 准备第一波团战 ===
Thread-0=>第一波团,我准备好了
Thread-1=>第一波团,我准备好了
Thread-2=>第一波团,我准备好了
Thread-3=>第一波团,我准备好了
Thread-4=>第一波团,我准备好了
Thread-5=>第一波团,我准备好了
Thread-6=>第一波团,我准备好了
Thread-7=>第一波团,我准备好了
Thread-8=>第一波团,我准备好了
Thread-9=>第一波团,我准备好了
=== 人齐了,开始团吧
=== 第一波团战结束 ===

总结

什么是并发工具:并发工具是一组工具类,主要是用来控制线程的执行流程,比如阻塞某个线程,以等待其他线程
倒计数器 CountDownLatch:用来表示阻塞某个(某些)线程,以等待其他多个线程的任务执行完成
循环栅栏 CyclicBarrier:用来表示多个线程之间的相互等待协作(阻塞)
信号量 Semaphore:用来表示允许同时访问指定资源的许可数(线程数)

区别 CountDownLatch CyclicBarrier Semaphore
可使用次数 单次 多次(循环使用) 多次(循环使用)
线程的阻塞 阻塞单个(多个)线程,以等待其他线程的执行 多个线程之间的相互阻塞 超过许可数,会阻塞
场景 1. 计数器
2. 统计任务执行时长
3. 多人对战游戏的开局等待
1. 大事化小,再合并
2. 多人对战游戏的团战
1. 数据库连接池

故乡明

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注