• 多线程工具类-CyclicBarrier使用案例


    1. CyclicBarrier 是什么?

    从字面上的意思可以知道,这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。

    它的作用就是会让所有线程都等待完成后才会继续下一步行动。

    举个例子,就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。

    2. 怎么使用 CyclicBarrier

    • 构造方法
    // parties 是参与线程的个数
    public CyclicBarrier(int parties)
        
    // 第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务
    public CyclicBarrier(int parties, Runnable barrierAction)
    
    • 重要方法
    public int await() throws InterruptedException, BrokenBarrierException
    public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
    // 解析:
    // 线程调用 await() 表示自己已经到达栅栏
    // BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时
    
    • 基本使用
    1. 需求

    一个线程组的线程需要等待所有线程完成任务后再继续执行下一次任务

    1. 代码实现
    public class CyclicBarrierDemo {
    	// 静态内部类
        static class TaskThread extends Thread {
            
            CyclicBarrier barrier;
            
            public TaskThread(CyclicBarrier barrier) {
                this.barrier = barrier;
            }
            
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    System.out.println(getName() + " 到达栅栏 A");
                    barrier.await();
                    System.out.println(getName() + " 冲破栅栏 A");
                    
                    Thread.sleep(2000);
                    System.out.println(getName() + " 到达栅栏 B");
                    barrier.await();
                    System.out.println(getName() + " 冲破栅栏 B");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        // 测试
        public static void main(String[] args) {
            int threadNum = 5;
            CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " 完成最后任务");
                }
            });
            for(int i = 0; i < threadNum; i++) {
                new TaskThread(barrier).start();
            }
        }
    }
    

    从控制台结果可以看出,所有线程会等待全部线程到达栅栏之后才会继续往下执行,并且最后到达的线程会完成 Runnable 的任务。

    3. CyclicBarrier 使用场景

    可以用于多线程计算数据,最后合并计算结果的场景。

    4. CyclicBarrier 与 CountDownLatch 区别

    • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
    • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
  • 相关阅读:
    .NET程序默认启动线程数
    TPL中Task执行的内联性线程重入
    Unity容器中的对象生存期管理
    C# 异步 TCP 服务器完整实现
    WPF中多源控制Button的状态
    C# 对 TCP 客户端的状态封装
    WPF异步MVVM等待窗体
    C#实现UDP分包组包
    C#实现RTP数据包传输
    PHP 传引用调用
  • 原文地址:https://www.cnblogs.com/hhddd-1024/p/15259227.html
Copyright © 2020-2023  润新知