Java多线程 之 CyclicBarrier源码分析

iTunes备份文件路径修改方法 因为以前的很多帖子iTunes都不是从微软下载的,而现在的iTunes一般都是微软商店里面的,它的路径为:“C:\Users\ 你的用户名 \Apple\MobileSync” (注:用户名,根据个人电脑名称更改)打开iTunes备份路径:“C:\Users\txh\AppData\Roaming\Apple Computer\MobileSync”,其中文件夹MobileSync就是用来存放备份文件的。创建你想备份纯在的目录创建备份文件目录(我的是G:/APPLE/Backup)2.粘贴的剪切文件目录。 阅读详情

​ 目录

1、背景介绍

2、运行实例

3、源码分析

4、CyclicBarrier图示


一、背景介绍

CyclicBarrier 字面直译意思是循环栅栏,他要做的事情是让一组各自执行自己任务的子线程共同到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时候,屏障才会开门。所有被屏障拦截的子线程才会继续运行,完成后续任务,如果后续同样有栅栏进行阻塞,循环往复执行同样的流程。

二、运行实例

下面先通过一个简单的实例感受一下CyclicBarrier的功能。

/**
 * @author: wenyixicodedog
 * @create: 2020-07-27
 * @description:
 */
public class TestCyclicBarrier {
​
    public static void main(String[] args) {
​
        CyclicBarrier barrier = new CyclicBarrier(4);
        for (int i = 0; i < barrier.getParties(); i++) {
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    try {
                        int a = new Random().nextInt((3000 - 1000) + 1) + 1000;
                        Thread.sleep(a);
                        System.out.println(Thread.currentThread().getName() + ", 通过了第" + j + "个障碍物, 耗时 " + ((double) a / 1000) + "s");
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        System.out.println("===============main 方法执行完毕===============");
    }
​
}

执行结果如下:

===============main 方法执行完毕===============
Thread-1, 通过了第0个障碍物, 耗时 1.042s
Thread-0, 通过了第0个障碍物, 耗时 1.872s
Thread-2, 通过了第0个障碍物, 耗时 2.017s
Thread-3, 通过了第0个障碍物, 耗时 2.244s
Thread-2, 通过了第1个障碍物, 耗时 1.264s
Thread-3, 通过了第1个障碍物, 耗时 1.997s
Thread-1, 通过了第1个障碍物, 耗时 2.333s
Thread-0, 通过了第1个障碍物, 耗时 2.889s
Thread-0, 通过了第2个障碍物, 耗时 1.042s
Thread-3, 通过了第2个障碍物, 耗时 1.047s
Thread-1, 通过了第2个障碍物, 耗时 1.262s
Thread-2, 通过了第2个障碍物, 耗时 2.287s

在这个场景中实现的功能是定义了四个线程,在每个线程的run方法中执行一个for循环,这个for循环体循环三次,在每一次循环中都调用barrier.await进行拦截当前线程执行,阻塞到栅栏处。代码并不复杂,通过看最终的执行结果也能够清晰地看出其执行规律,四个线程在每次跨越栅栏的顺序是不一定的,但是三个栅栏跨越的时机顺序是固定的,只有通过第一个栅栏、第一个栅栏才能通过第二个栅栏,这样一批线程在局部执行无序地、整体跨越栅栏有序的在工作。

三、源码分析

CyclicBarrier的实现其实也并不复杂。它的源码当中可以发现其核心功能是使用ReentrantLock和Condition组合进行实现的。

首先我们看其构造方法。

 public CyclicBarrier(int parties) {
        this(parties, null);
    }
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }
​
    // 可重入锁
    private final ReentrantLock lock = new ReentrantLock();
    // Condition条件等待队列
    private final Condition trip = lock.newCondition();
    // 线程数量
    private final int parties;
    // 换代前执行的任务
    private final Runnable barrierCommand;
    //表示每一个栅栏的当前代
    private Generation generation = new Generation();

构造方法首先判断parties的合法性,如果不大于零,就直接抛出异常,然后赋值成员变量,parties表示线程数量,count用来计数,初始值也是parties,barrierCommand表示换代前执行的任务,通过构造方法可以指定。除了这些成员变量还定义了ReentrantLock可重入锁、lock.newCondition Condition条件等待队列、generation每一个栅栏的当前代。

接下来barrier.getParties()方法很简单是用来获取线程数量parties。

然后最重要的是barrier.await()方法,这个方法用来拦截当前线程。让其在栅栏处等待。

await方法直接调用dowait方法,传入参数false,0L表示没有设置等待时间,如果该线程没有被唤醒或者响应中断异常将会一直处于等待状态。

public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // 不会发生
        }
    }

doWait方法源码如下:

private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException, TimeoutException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //创建当前generation代
            final Generation g = generation;
            //当前栅栏是否被打翻
            if (g.broken)
                //如果当前栅栏被踢翻,直接抛出异常
                throw new BrokenBarrierException();
            //如果线程被中断过,踢翻当前栅栏,直接抛出异常
            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }
            //计数器减1
            int index = --count;
            //如果计数器减1之后为0则需唤醒所有线程并转换到下一代
            if (index == 0) {  
                //标志是否换代之前执行了command任务
                boolean ranAction = false;
                try {
                    //执行command任务
                    //唤醒所有线程前先执行指定的任务
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    ranAction = true;
                    //执行command任务之后进行换代
                    nextGeneration();
                    //执行command任务之后进行换代完成返回0
                    return 0;
                } finally {
                    if (!ranAction)
                        //如果ranAction仍然为false,就踢翻栅栏。
                        breakBarrier();
                }
            }
​
            // 循环直到唤醒,中断或超时
            for (;;) {
                try {
                    if (!timed)
                        trip.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方法中首先会创建当前generation代,然后对当前栅栏是否被打翻进行判断,如果这个时候栅栏被踢翻,就直接抛出异常,然后判断线程是否被中断过,如果中断过就直接抛出异常,然后接下来分为两部分:

①、将计数器count减1,减完后进行判断是否等于0,如果等于0的话就会先去执行之前指定好的command任务,执行完之后再调用nextGeneration方法将栅栏进行换代,在换代方法中会将所有线程唤醒,将计数器的值重新设为parties,最后会重新设置栅栏代次,就进入了下一代的执行周期。

②、如果计数器不等于0的话就进入for循环,根据时间参数来决定是调用trip.awaitNanos(nanos)还是trip.await()方法,如果调用awaitNanos,意味着当前线程已经成功获得与该条件对象绑定的重入锁,否则调用该方法时会抛出IllegalMonitorStateException。若指定时间内被signal()或signalALL()唤醒则返回nanosTimeout减去已经等待的时间,就是相对于超时时间的剩余时间;若指定时间内有其它线程中断该线程,则抛出InterruptedException并清除当前线程的打断状态;若指定时间内未收到通知,则返回0或负数。如果调用await使当前线程加入await() 等待队列中,并释放锁,当其他线程调用signal()会重新请求锁。如果在等待过程中当前线程被中断就会执行breakBarrier方法,这也就意味着如果在等待过程中任一线程被中断,则当前代执行就结束了,所有之前被阻塞的线程都会被唤醒。线程唤醒后会进行三个判断:

①、是否因为breakBarrier方法踢翻栅栏被唤醒,如果是则抛出异常;

②、是否是正常的换代操作而被唤醒,如果是则返回计数器的值;

③、是否因为超时而被唤醒,如果是的话就调用breakBarrier打破栅栏并抛出异常。

如果其中有一个线程因为等待超时而退出,那么整盘游戏也会结束,其他线程都会被唤醒。

if (timed && nanos <= 0L) {
                 breakBarrier();
                 throw new TimeoutException();
         }

CyclicBarrier对外提供的方法不多,有些方法只是在内部使用,我们看下reset方法,其他方法都很好理解。

源码如下:

 public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 踢翻栅栏
            breakBarrier();  
            // 换代操作  
            nextGeneration(); 
        } finally {
            lock.unlock();
        }
    }
​
    private void breakBarrier() {
        // 设置当前代为broken
        generation.broken = true;
        // 重置计数器
        count = parties;
        // 唤醒所有等待线程
        trip.signalAll();
    }
​
    private void nextGeneration() {
        // 唤醒所有等待线程
        trip.signalAll();
        // 重置计数器
        count = parties;
        // 重新设置当前代
        generation = new Generation();
    }

相关注释都已经写的很清楚。reset主要就两部分操作:踢翻栅栏和更新当前代操作。

如果我们对之前的示例进行稍微改造下,我们再看其执行过程。

public class TestCyclicBarrier {
​
    public static void main(String[] args) {
​
        CyclicBarrier barrier = new CyclicBarrier(4);
        for (int i = 0; i < barrier.getParties(); i++) {
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    try {
                        int a = new Random().nextInt((3000 - 1000) + 1) + 1000;
                        Thread.sleep(a);
                        System.out.println(Thread.currentThread().getName() + "通过了第" + j + "个障碍物, 耗时 " + ((double) a / 1000) + "s");
                        if (j == 0) {
                            barrier.reset();
                        }
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        System.out.println("===============main 方法执行完毕===============");
    }
​
}

我们在第一次线程成批执行的时候多了个重置操作。这个时候执行结果如下:

===============main 方法执行完毕===============
Thread-1通过了第0个障碍物, 耗时 1.696s
Thread-3通过了第0个障碍物, 耗时 1.773s
java.util.concurrent.BrokenBarrierException
  at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
  at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
  at com.cloud.web.concurrentprogrammer.cyclicbarrier.TestCyclicBarrier.lambda$main$0(TestCyclicBarrier.java:27)
  at java.lang.Thread.run(Thread.java:748)
Thread-0通过了第0个障碍物, 耗时 2.153s
java.util.concurrent.BrokenBarrierException
  at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
  at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
  at com.cloud.web.concurrentprogrammer.cyclicbarrier.TestCyclicBarrier.lambda$main$0(TestCyclicBarrier.java:27)
  at java.lang.Thread.run(Thread.java:748)
Thread-2通过了第0个障碍物, 耗时 2.344s
java.util.concurrent.BrokenBarrierException
  at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
  at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
  at com.cloud.web.concurrentprogrammer.cyclicbarrier.TestCyclicBarrier.lambda$main$0(TestCyclicBarrier.java:27)
  at java.lang.Thread.run(Thread.java:748)
Thread-0通过了第1个障碍物, 耗时 1.849s
Thread-3通过了第1个障碍物, 耗时 2.522s
Thread-1通过了第1个障碍物, 耗时 2.929s
Thread-1通过了第2个障碍物, 耗时 1.852s
Thread-3通过了第2个障碍物, 耗时 2.424s
Thread-0通过了第2个障碍物, 耗时 2.64s
Thread-2通过了第1个障碍物, 耗时 2.808s
Thread-2通过了第2个障碍物, 耗时 2.507s

这个时候确实会出现异常,这是因为我们在创建CyclicBarrier实例的时候已经创建了一个Generation当前代,但是第一个线程执行的时候执行到reset方法,踢翻了栅栏,设置栅栏状态为broken,然后唤醒所有线程,又重新创建了新一代。当第二个线程执行到reset方法的时候,和第一个线程同样的过程,这个时候第二个线程在踢翻栅栏唤醒所有等待线程的时候会把第一个线程唤醒,第一个线程被唤醒后执行后面的操作(doWait方法中✨标注),这个时候进行判断是因为什么原因被唤醒的,发现是被踢翻栅栏唤醒,这个时候就会执行doWait方法249行代码抛出异常,后续线程执行过程类似。

四、CyclicBarrier图示

我们感受了CyclicBarrier的执行功能,由此也分析了其源码实现,接下来最后我们以CyclicBarrier在本例中的执行图示作为结束。

 

更多内容持续更新中,感兴趣的朋友请移步至个人公众号,谢谢支持😜😜......

公众号:wenyixicodedog

解决Qt字体问题:QFontDatabase: Cannot find font directory xx/lib/fonts 1.直接在main函数里设置app的整体字体库.这个错误提示比较明显的就是字体库缺失。 阅读详情

相关推荐

Unity基础篇-----Input输入

2、Input.GetTouch()方法,主要用于移动端开发使用,此方法主要获取触摸屏幕的操作数据,首先通过Input.touchCount这个方法获取到手指触摸屏幕的次数,通过GetTouch方法传输触摸次数,调用Touch结构判断手指的状态来是否为设定的状态,符合的话则执行相关内容。参数(“Horizontal”)表示左右的值,值为-1时,表示你在一直按下左方向对应的按键、设备类型为手柄时,表示你把推杆推到了最左边,为0时为默认位置,手柄中对应正中间,为1时与-1时对应的情况正好相反。

why820mmm的博客 3495

CyclicBarrier源码分析

一、简介 在理解CyclicBarrier之前,最好先熟悉一下CountDownLatch的工作原理,这两个工具类都能达到线程等待的效果,但它们的侧重点有所不同,CountDownLatch只能使用一次,当它的计数器为0时会去唤醒所有同步队列中等待的线程,之后就不可用了。而CyclicBarrier的计数器可以被重置,达到重复使用的效果,所以它也就更适用于复杂的业务场景,比如如果计算发生错误时,可以通过重置计算器,让线程重复执行一次 CyclicBarrier:回环栅栏(循环屏障),通过它可以实现让一组线程

sermonlizhi的博客 653

上证指数30年k线图_金融占星简单解读上证指数30年历史行情

阅读此文需要一定的占星基础知识,本人对于金融知识了解甚少,如有描述错误请包涵指正!影响大众事件发展趋势的都是外行星,即木星-冥王星这5颗,由于时间跨度长达30年,绘制社会行星的K线图工作量太大,所以只以时代行星对这30年行情的简单解读作为分享,在今后的短期分析中会逐渐加入社会行星,甚至在个股分析上还会加入个人行星。那即使只绘制时代行星,所展现出来的信息也无法在一张图上画出来,否则太乱难以分辨,所以...

weixin_39831242的博客 1675

深入理解 CyclicBarrier【源码分析】

CyclicBarrier 字面意思是环栅栏,是 JUC 下的一个并发工具,跟 CountDownLatch 很相似,都可以使线程先等待然后再执行,但是它的功能比 CountDownLatch 更加复杂和强大, CountDownLatch 是一个或者多个线程等待另外一批线程执行完毕后,在接着执行,而 CyclicBarrier 是等待一批线程到达某个状态之后再同时开始执行,回环的意思是当所有的线程被释放后,CyclicBarrier 可以被重启,也就是可以重复使用。如有错误的地方欢迎指出纠正。

weixin_42118323的博客 705

ChatGPT设置密钥后Codex免手机验证:配置顺序与身份凭证复用机制

API Key 是一种用于身份识别的凭证,其核心原理是通过预配置的密钥替代交互式登录流程。在开发工具中,密钥认证优先级通常高于会话认证,当本地存在有效密钥时,工具会直接复用该凭证,从而减少重复验证环节。这种机制的技术价值在于提升开发效率与配置一致性,尤其适用于多设备切换、CI/CD 流水线及编程辅助工具等场景。以 Codex 为例,在 ChatGPT 界面提前配置 API 密钥后,Codex 启动时可读取持久化存储的密钥,避免触发手机号验证,实现身份凭证的跨入口复用。

weixin_33940469的博客 490

模仿学习算法——ATC / Diffusion Policy

最近又开始接触具身智能相关的一些工作,本文主要介绍三篇较为基础的用来做模仿学习的算法,后续有空再进一步学习分享RT系列和Pi0等文章ACT算法全称为Action Chunking with Transformers,发表于《Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware》,该论文主要内容为如何使用低成本的硬件和模仿学习算法来实的双手操作,我们主要对算法部分进行剖析ACT算法的网络结构如下图所示,使用的采用的是生成式模型VA

weixin_44580210的博客 5255

【并发编程】CyclicBarrier 源码分析

等待/通知模型、屏障等。

yhl_jxy的博客 1314

YOLOv5+Astra Pro Plus深度相机:手把手教你实现实时目标检测(附ROS配置技巧)

本文详细介绍了如何将YOLOv5目标检测算法与Astra Pro Plus深度相机结合,构建实时目标检测系统。内容涵盖从硬件选型、环境搭建、ROS配置到YOLOv5部署与深度信息融合的完整流程,并分享了性能优化、避障算法等实战技巧,帮助开发者在机器人视觉等场景中快速实现智能感知应用。

weixin_28292761的博客 389

10、深入理解AQS之循环栅栏CyclicBarrier

CyclicBarrier基于 ReentrantLock + ConditionObject实现,CyclicBarrier的构造函数中必须指定parties,同时对象generation,内部持有布尔型属性表示当前CyclicBarrier执行过程中是否有超时、异常、中断的情况。parties是初始待执行线程数,在构造函数中会将parties赋给计数值count,每当一个线程执行await(),count就会减1。

sproutBoy的博客 1134

医疗AI Agent实战:从零搭建一个能看病的智能助手(附完整代码)

本文详细介绍了如何从零搭建一个医疗AI Agent智能助手,涵盖核心架构设计、症状推理引擎开发、安全与合规实现以及系统集成等关键环节。通过完整的代码示例和实战案例,帮助开发者快速构建具备医疗咨询能力的智能Agent,提升医疗服务的效率和质量。

ss78901的博客 468

5分钟搞定Nano-Banana图片编辑API对接:从Base64编码到生成图片全流程

本文详细介绍了如何快速对接Nano-Banana图片编辑API,基于gemini-2.5-flash-image-preview模型,从环境准备、Base64编码到API调用的全流程。通过实战示例和优化技巧,帮助开发者高效集成AI图片处理能力,提升产品竞争力。

dog123的博客 260

java多线程 CyclicBarrier源码分析

目录 简介 内部类Generation,字段lock,trip,parties,barrierCommand,generation,count 方法nextGeneration,breakBarrier,dowait,2个构造函数 方法getParties,2个await,isBroken,reset,getNumberWaiting 简介 package java.util.concurrent; import java.util.concurrent.locks.Condition; im

今天吃了吗的博客 240

【sealos安装指南】基于 Sealos 安装 Kubernetes 1.33.6 高可用集群

本文介绍使用Sealos工具快速搭建Kubernetes集群的详细指南。Sealos简化了K8s部署流程,自动完成系统调优,适合新手学习使用。文章提供了服务器规划、环境准备、在线/离线两种安装方式的具体步骤,包括主机名设置、swap关闭、数据目录配置等。重点讲解了Sealos的安装命令参数说明,以及添加/删除节点等常用操作。推荐使用Calico网络组件确保稳定性,并附有安装成功后的验证截图。该指南能帮助用户快速搭建一个包含master和worker节点的K8s集群,底层基于containerd运行。

欢迎你们到来,希望能帮到大家 463

Java多线程系列(八)—CyclicBarrier源码分析

Java多线程系列(八)—CyclicBarrier源码分析 CyclicBarrier是一个同步辅助类,允许一组相关线程相互等待,直到所有线程都到达某个公共屏障点;因为该屏障点在释放后可以循环重用,所以称为循环屏障; 个人主页:tuzhenyu’s page 原文地址:Java多线程系列(八)—CyclicBarrier源码分析 (0) CyclicBarrier循环

tuzhenyu的博客 359

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

cyclicbarrier java_Java并发系列[8]----CyclicBarrier源码分析

现实生活中我们经常会遇到这样的情景,在进行某个活动前需要等待人全部都齐了才开始。例如吃饭时要等全家人都上座了才动筷子,旅游时要等全部人都到齐了才出发,比赛时要等运动员都上场后才开始。在JUC包中为我们提供Java并发系列[8]----CyclicBarrier源码分析了一个同步工具类能够很好的模拟这类场景,它就是CyclicBarrier类。利用CyclicBarrier类可以实现一组线程相互等待...

weixin_42516967的博客 169

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

《Java源码分析》:CyclicBarrier(part two)

《Java源码分析》:CyclicBarrier(part two)在上篇博文中http://blog.youkuaiyun.com/u010412719/article/details/52156588,我们看了关于CyclicBarrier应用的一些例子,也得出的使用CyclicBarrier时的相关结论。回顾下我们在上篇博文中了解了关于CyclicBarrier的相关知识点如下:1、CyclicBarri

wojiushimogui的博客 1009

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

CyclicBarrier 深入源码解析

  CyclicBarrier意为“循环栅栏”,是一个可循环利用的屏障。CyclicBarrier可以使指定数量线程到达阻塞点后继续后续任务。   演示示例:   首先,新建一个线程类,用于模拟多线程环境。 package com.securitit.serialize.juc; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierThread extends Thread { // CyclicBarrier实例.

键盘上流淌的日子 8261

java多线程学习之【CyclicBarrier】

本文主要是讲解CyclicBarrier的概念,基本用法,使用场景,底层代码原理剖析。按照源码注释,翻译成中文,就是以下内容:CyclicBarrier 提供了一些方法:主要用于多线程等待,Runnable命令执行后,多线程执行直到释放。代码如下 四、源码剖析 CyclicBarrier 的源码在JUC并发工具中,相对复杂点: CyclicBarrier 构造函数中指定的count和可选的Runnable命令; await(),等待直到其他线程都到达栅栏,并且每执行一次会将全局变量count减去1

blackoon88的博客 388

【JUC源码】并发工具:CyclicBarrier 源码分析&应用示例

栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。 1.应用示例 可以用于多线程计算数据,最后合并计算结果的场景。 例如,用一个Excel保存了用户所有银行流水,每个Sheet保存一个账户近一年的每笔银行流

A minor 298

java 并发之CyclicBarrier 原理

CyclicBarrier简介CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。注意比较CountDownLatch和CyclicBarrier:(01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行...

weixin_34008805的博客 103

Java多线程 -- JUC包源码分析11 -- CyclicBarrier源码分析

在前面的篇章中,讲解了ReentrantLock + Condition,并讲述了2者结合的一个典型应用:ArrayBlockingQueue/LinkedBlockingQueue。今天讲述2者结合的另一个典型应用:CyclicBarrier。CyclicBarrier的概念要介绍CyclicBarrier这个概念,可以从下面这个比喻开始:一个小公司的所有人周六要出去团建,大家提前商定好周六早上

软件开发与架构领域 -体系化知识分享 1126

【JUC深度解析】Java并发神器之CyclicBarrier:原理、源码与实战全攻略

【JUC深度解析】Java并发神器之CyclicBarrier:原理、源码与实战全攻略

嗨,欢迎来到我的 优快云 博客小天地!一名深耕多年的技术发烧友。在这里,我将把日常工作中积累的宝贵经验,从复杂架构设计的精妙之处,到代码优化的实战技巧,毫无保留地分享给大家。 2446

Java并发 JUC工具类:CyclicBarrier详解

对于CountDownLatch,其他线程为游戏玩家,比如英雄联盟,主线程为控制游戏开始的线程。在所有的玩家都准备好之前,主线程是处于等待状态的,也就是游戏不能开始。当所有的玩家准备好之后,下一步的动作实施者为主线程,即开始游戏。对于CyclicBarrier,假设有一家公司要全体员工进行团建活动,活动内容为翻越三个障碍物,每一个人翻越障碍物所用的时间是不一样的。但是公司要求所有人在翻越当前障碍物之后再开始翻越下一个障碍物,也就是所有人翻越第一个障碍物之后,才开始翻越第二个,以此类推。

weixin_45773632的博客 1475

Java-juc(5) CyclicBarrier 源码分析

文章目录CyclicBarrier分析CyclicBarrier介绍CyclicBarrier使用CyclicBarrier源码分析 CyclicBarrier分析 本文源码基于JDK8。因为本人水平有限,错误和不足之处在所难免,欢迎指出错误和不足之处,一起进步。 阅读这篇文章最好对AQS有一定的了解。 CyclicBarrier介绍 CyclicBarrier和juc中另一个同步工具CountDownLatch非常像,使用CyclicBarrier可以使多个线程阻塞等待,等到所有线程都准备完毕了以后再

qq_19007335的博客 213

Java高并发编程基础三大利器之CyclicBarrier

引言 前面一篇文章我们《java高并发编程基础三大利器之​​CountDownLatch》它有一个缺点,就是它的计数器只能够使用一次,也就是说当计数器( state)减到为 0的时候,如果 再有线程调用去 await() 方法,该线程会直接通过,不会再起到等待其他线程执行结果起到同步的作用。为了解决这个问题 CyclicBarrier就应运而生了。 什么是CyclicBarrier CyclicBarrier是什么?把它拆开来翻译就是循环( Cycle)和屏障( Barrier)它的主...

Java架构师之路的博客 151

JUC第二十七讲:JUC工具类: CyclicBarrier详解

本文是JUC第二十七讲,JUC工具类: CyclicBarrier详解。CyclicBarrier中文名为:循环栅栏,底层是基于 ReentrantLock 和 AbstractQueuedSynchronizer 来实现的,在理解的时候最好和 CountDownLatch 放在一起理解。

Jet_qi的博客 548
上一篇: 数据结构和算法 之 LinkedHashMap实现LRU算法
下一篇: 恕我孤陋寡闻,因为这次面试才第一次听说Java中的函数闭包
wenyixicodedog
博客等级 码龄8年 87粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值