当前位置:

首页 > 编程开发 > Java中的CyclicBarrier源码分析

Java中的CyclicBarrier源码分析

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

本文目录

      CyclicBarrier简介

      对于CountDownLatch,其他线程为游戏玩家,比如英雄联盟,主线程为控制游戏开始的线程。在所有的玩家都准备好之前,主线程是处于等待状态的,也就是游戏不能开始。当所有的玩家准备好之后,下一步的动作实施者为主线程,即开始游戏。

      对于CyclicBarrier,假设有一家公司要全体员工进行团建活动,活动内容为翻越三个障碍物,每一个人翻越障碍物所用的时间是不一样的。但是公司要求所有人在翻越当前障碍物之后再开始翻越下一个障碍物,也就是所有人翻越第一个障碍物之后,才开始翻越第二个,以此类推。类比地,每一个员工都是一个“其他线程”。当所有人都翻越的所有的障碍物之后,程序才结束。而主线程可能早就结束了,这里我们不用管主线程。

      CyclicBarrier源码分析

      类的继承关系

      CyclicBarrier没有显示继承哪个父类或者实现哪个父接口, 所有AQS和重入锁不是通过继承实现的,而是通过组合实现的。

      public class CyclicBarrier {}
      ```  
      
      ### 类的内部类
      
      CyclicBarrier类存在一个内部类Generation,每一次使用的CycBarrier可以当成Generation的实例,其源代码如下
      
      ```java
      private static class Generation {
      boolean broken = false;
      }

      说明: Generation类有一个属性broken,用来表示当前屏障是否被损坏。

      类的属性

      public class CyclicBarrier {
      
      /** The lock for guarding barrier entry */
      // 可重入锁
      private final ReentrantLock lock = new ReentrantLock();
      /** Condition to wait on until tripped */
      // 条件队列
      private final Condition trip = lock.newCondition();
      /** The number of parties */
      // 参与的线程数量
      private final int parties;
      /* The command to run when tripped */
      // 由最后一个进入 barrier 的线程执行的操作
      private final Runnable barrierCommand;
      /** The current generation */
      // 当前代
      private Generation generation = new Generation();
      // 正在等待进入屏障的线程数量
      private int count;
      }

      说明: 该属性有一个为ReentrantLock对象,有一个为Condition对象,而Condition对象又是基于AQS的,所以,归根到底,底层还是由AQS提供支持。

      类的构造函数

      CyclicBarrier(int, Runnable)型构造函数

      public CyclicBarrier(int parties, Runnable barrierAction) {
      // 参与的线程数量小于等于0,抛出异常
      if (parties <= 0) throw new IllegalArgumentException();
      // 设置parties
      this.parties = parties;
      // 设置count
      this.count = parties;
      // 设置barrierCommand
      this.barrierCommand = barrierAction;
      }

      说明: 该构造函数可以指定关联该CyclicBarrier的线程数量,并且可以指定在所有线程都进入屏障后的执行动作,该执行动作由最后一个进行屏障的线程执行。

      CyclicBarrier(int)型构造函数

      public CyclicBarrier(int parties) {
      // 调用含有两个参数的构造函数
      this(parties, null);
      }

      说明: 该构造函数仅仅执行了关联该CyclicBarrier的线程数量,没有设置执行动作。

      核心函数 - dowait函数

      此函数为CyclicBarrier类的核心函数,CyclicBarrier类对外提供的await函数在底层都是调用该了doawait函数,

      其源代码如下:

      private int dowait(boolean timed, long nanos)
      throws InterruptedException, BrokenBarrierException,
      TimeoutException {
      // 保存当前锁
      final ReentrantLock lock = this.lock;
      // 锁定
      lock.lock();
      try {
      // 保存当前代
      final Generation g = generation;
      
      if (g.broken) // 屏障被破坏,抛出异常
      throw new BrokenBarrierException();
      
      if (Thread.interrupted()) { // 线程被中断
      // 损坏当前屏障,并且唤醒所有的线程,只有拥有锁的时候才会调用
      breakBarrier();
      // 抛出异常
      throw new InterruptedException();
      }
      
      // 减少正在等待进入屏障的线程数量
      int index = --count;
      if (index == 0) { // 正在等待进入屏障的线程数量为0,所有线程都已经进入
      // 运行的动作标识
      boolean ranAction = false;
      try {
      // 保存运行动作
      final Runnable command = barrierCommand;
      if (command != null) // 动作不为空
      // 运行
      command.run();
      // 设置ranAction状态
      ranAction = true;
      // 进入下一代
      nextGeneration();
      return 0;
      } finally {
      if (!ranAction) // 没有运行的动作
      // 损坏当前屏障
      breakBarrier();
      }
      }
      
      // loop until tripped, broken, interrupted, or timed out
      // 无限循环
      for (;;) {
      try {
      if (!timed) // 没有设置等待时间
      // 等待
      trip.await();
      else if (nanos > 0L) // 设置了等待时间,并且等待时间大于0
      // 等待指定时长
      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) { // 设置了等待时间,并且等待时间小于0
      // 损坏屏障
      breakBarrier();
      // 抛出异常
      throw new TimeoutException();
      }
      }
      } finally {
      // 释放锁
      lock.unlock();
      }
      }

      核心函数 - nextGeneration函数

      此函数在所有线程进入屏障后会被调用,即生成下一个版本,所有线程又可以重新进入到屏障中,

      其源代码如下:

      private void nextGeneration() {
      // signal completion of last generation
      // 唤醒所有线程
      trip.signalAll();
      // set up next generation
      // 恢复正在等待进入屏障的线程数量
      count = parties;
      // 新生一代
      generation = new Generation();
      }

      在此函数中会调用AQS的signalAll方法,即唤醒所有等待线程。如果所有的线程都在等待此条件,则唤醒所有线程。

      其源代码如:

      public final void signalAll() {
      if (!isHeldExclusively()) // 不被当前线程独占,抛出异常
      throw new IllegalMonitorStateException();
      // 保存condition队列头节点
      Node first = firstWaiter;
      if (first != null) // 头节点不为空
      // 唤醒所有等待线程
      doSignalAll(first);
      }
      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。