• 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=>第一波团,我准备好了
    === 人齐了,开始团吧
    === 第一波团战结束 ===

    总结

    1. 什么是并发工具:并发工具是一组工具类,主要是用来控制线程的执行流程,比如阻塞某个线程,以等待其他线程
    2. 倒计数器 CountDownLatch:用来表示阻塞某个(某些)线程,以等待其他多个线程的任务执行完成
    3. 循环栅栏 CyclicBarrier:用来表示多个线程之间的相互等待协作(阻塞)
    4. 信号量 Semaphore:用来表示允许同时访问指定资源的许可数(线程数)
    区别CountDownLatchCyclicBarrierSemaphore
    可使用次数 单次 多次(循环使用) 多次(循环使用)
    线程的阻塞 阻塞单个(多个)线程,以等待其他线程的执行 多个线程之间的相互阻塞 超过许可数,会阻塞
    场景 1. 计数器
    2. 统计任务执行时长
    3. 多人对战游戏的开局等待
    1. 大事化小,再合并
    2. 多人对战游戏的团战
    1. 数据库连接池
    故乡明
  • 相关阅读:
    【SSH网上商城项目实战15】线程、定时器同步首页数据(类似于CSDN博客定期更新排名)
    【SSH网上商城项目实战14】商城首页UI的设计
    Spring工具类:WebApplicationContextUtils
    多线程技术: 两个线程交替打印奇数和偶数
    常见的几种异常类型Exception
    【SSH网上商城项目实战13】Struts2实现文件上传功能
    【SSH网上商城项目实战12】添加和更新商品功能的实现
    【SSH网上商城项目实战11】查询和删除商品功能的实现
    【SSH网上商城项目实战10】商品类基本模块的搭建
    如何防止通过IP地址访问Tomcat管理页面
  • 原文地址:https://www.cnblogs.com/luweiweicode/p/14764003.html
Copyright © 2020-2023  润新知