CyclicBarrier 源码

news2024/11/25 2:24:14

CyclicBarrier 源码

1.构造方法

参数 n 为等待的线程数

CyclicBarrier cyclicBarrier = new CyclicBarrier(n);
  public CyclicBarrier(int parties) {
        this(parties, null);
    }

参数 barrierAction 为当等待的线程达到 参数 parties 时执行的线程任务

blic CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }

可以看到此处对 parties 的值进行了限制 如果少于0将抛出运行时异常 IllegalArgumentException

2.await() 方法

如果等待的线程没有达到 parties,那么线程进入等待状态 , 除非 :

  1. 线程等待超时
  2. 被其他线程唤醒
  3. 被中断
  4. 调用 reset() 方法
 public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

重载方法

 public int await(long timeout, TimeUnit unit)
        throws InterruptedException,
               BrokenBarrierException,
               TimeoutException {
        return dowait(true, unit.toNanos(timeout));
    }

dowait 方法

   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;
            //如果当前计算器等于0 (所有线程都已进入屏障点)
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                		//执行打破屏障时的任务
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    //记录动作
                    ranAction = true;
                    //唤醒所有等待线程
                    nextGeneration();
                    //返回
                    return 0;
                } finally {
                		//如过已经执行过动作 就不用在执行 breakBarrier 方法
                    if (!ranAction)
                    		//标记当前屏障已经被打破,并唤醒所有线程
                        breakBarrier();
                }
            }

            // 循环等待 直到所有线程达到屏障点,超时,屏障被破坏,被中断
            for (;;) {
                try {
                		//如果没有设置超时时间
                    if (!timed)
                    		//等待,直到所有线程都到达屏障点
                        trip.await();
                    else if (nanos > 0L)
                    		// 设置了超时时间则在规定时间内等待所有线程进入屏障
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                		// 判断 是否已经执行过 nextGeneration 创建了一个新的 generation 对象,
                		// 并且 generation是否已经被标记为被破坏
                    if (g == generation && ! g.broken) {
                    		// 如果没有创建新的generation 对象,并且未被破坏,则打破当前屏障
                        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();
								
								//如果不相等,表示已经进入下一个屏障  并返回当前线程的index
                if (g != generation)
                    return index;

								//如果超时
                if (timed && nanos <= 0L) {
                		//打破屏障,唤醒当前屏障等待的所有线程
                    breakBarrier();
                    //抛出超时异常
                    throw new TimeoutException();
                }
            }
        } finally {
        		//释放锁
            lock.unlock();
        }
    }

trip对象为当前锁Lock的条件对象

trip.await()
    private final ReentrantLock lock = new ReentrantLock();

    private final Condition trip = lock.newCondition();

如果进入屏障点的线程数已达到要求

      if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    ranAction = true;
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction)
                        breakBarrier();
                }
            }

ranAction 用于记录动作. 如果屏障被打破时执行的线程任务抛出异常,也要保证唤醒所有等待线程,并标记当前屏障被打破

 boolean ranAction = false;
 
 # 只有 command.run() 执行成功 ranAction 的值 才会时 true
 
     if (command != null)
                        command.run();
                    ranAction = true;

finally 代码块用来保证等待线程的释放 及 保证当前屏障被标记已经打破

finally {
    if (!ranAction)
        breakBarrier();
}

nextGeneration 唤醒等待线程,开启下一个屏障,还原count的值

//唤醒全部等待线程
trip.signalAll();
//开启下一个屏障 还原count的值
count = parties;
generation = new Generation();

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/725084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RCE漏洞利用挖掘方法

RCE漏洞利用挖掘方法 一、从命令执行漏洞到getshell二、命令执行漏洞详解2.1、靶场实操—DVWA&#xff08;Low级别&#xff09;2.2、靶场实操—DVWA&#xff08;Medium级别&#xff09;2.3、靶场实操—DVWA&#xff08;High级别&#xff09;2.4、靶场实操—DVWA&#xff08;Imp…

form表单使用Select 选择器

案例: ps&#xff1a;年度的值类型要与select 选择器中 value 类型一致&#xff01;&#xff01; 如果input框中显示的是数字&#xff0c;说明年度的值没有与选择器中的的value一致&#xff01;&#xff01;&#xff01; YearNum 要与 value 类型一致&#xff01;&#xff01…

【第三章 flutter学习之Dart基础(上)】

文章目录 一、入口方法的定义方式二、Dart变量和常量三、Dart常用数据类型四、Dart运算符与类型转换及循环语句五、自定义方法六、Dart静态成员、操作符、类的继承七、接口八、接口分离写法九、一个类实现多个接口 一、入口方法的定义方式 main(){print(hello world) } //下边…

Docker学习笔记24

Docker Swarm 搭建&#xff1a; 主机名系统版本IP地址功能swarm-1centos7.9192.168.17.10管理节点swarm-2centos7.9192.168.17.20工作节点swarm-3centos7.9192.168.17.30工作节点 CPU、Memory、Disk不做要求。 准备IP地址和主机名&#xff1a; hostnamectl set-hostname swa…

测试不容易,入坑请注意!

“零基础入门&#xff0c;保证就业&#xff0c;钱多&#xff0c;事少&#xff01;” 绝大部分培训机构的招生话术不外乎如此&#xff0c;骗了一波又一波钱多人傻的人入坑测试。而在报名前&#xff0c;会进行考试评估学员是否适合从业软件测试的机构很难见到。如果有&#xff0…

几何光学软件

光线追踪器 从手册中&#xff1a; https://arachnoid.com/OpticalRayTracer/ OpticalRayTracer 是一款免费 (GPL) 跨平台应用程序&#xff0c;用于分析透镜和反射镜系统。 它使用光学原理和虚拟光具座来预测多种普通和奇异镜头类型以及平面镜和曲面镜的行为。 OpticalRayTracer…

搭建ssl双向验证python

生成证书 客户端和服务端搭建 https simple-https-server.py # run as follows: python simple-https-server.py # then in your browser, visit: # https://localhost import ssl import http.serverserverAddress (0.0.0.0, 443) httpd http.server.HTTPServer(serverA…

【力扣】设计内存分配器(高效实现)

题目 给你一个整数 n &#xff0c;表示下标从 0 开始的内存数组的大小。所有内存单元开始都是空闲的。 请你设计一个具备以下功能的内存分配器&#xff1a; 分配 一块大小为 size 的连续空闲内存单元并赋 id mID 。 释放 给定 id mID 对应的所有内存单元。 注意&#xff1a;…

面试官当面夸奖完我后,反手把我挂了...只能说这套路太..

最近几个朋友找我聊天&#xff0c;给我讲述了面试过程中遇到的一些不太理解的事情。作为一个技术面试官&#xff0c;今天来分享 9 个面试相关的套路。 1.自我介绍 自我介绍是一个重要的开始&#xff0c;好的开始是成功的一半。不需要太多花里胡哨的东西&#xff0c;简单、清楚…

超详细:阿里云服务器地域和可用区选择方法

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

文件行读写

#include<stdio.h> #include<stdlib.h> #include<string.h> int main01() {FILE* fpfopen("D:/a.txt","r");//打开文件 if(fpNULL) printf("打开文件失败\n");char* p(char*)malloc(sizeof(char)*100);memset(p,0,100);fge…

架构课学习笔记:职业成长

架构师没有明确的定义&#xff0c;郭老师提出具备的能力&#xff1a;就是为一个复杂系统设计软件的能力&#xff0c;以及引导研发团队实施的能力。从5个 阶段来看对应的能力维度&#xff1a;结构化设计、解决横向问题、解决跨领域冲突、正确的技术决策和创造生存优势。 一结构…

树结构 根据关键字过滤

案例&#xff1a; 默认 过滤之后 直接看代码&#xff1a; <divclass"grid-content bg-purple"style"background-color: #fff"><p>单位列表</p><!-- defaultProps :这个里面的字段要与后端返回过来的字段一致 --><el-inputplac…

C++笔记之sizeof()判断对象所占内存空间的大小以及字符数组的长度

C笔记之sizeof()判断对象所占内存空间的大小以及字符数组的长度 code review! 文章目录 C笔记之sizeof()判断对象所占内存空间的大小以及字符数组的长度1.C笔记之sizeof()判断对象所占内存空间的大小2.C笔记之sizeof()判断数组的长度3.C笔记之strlen在字符数组中的使用 1.C笔…

《动手学深度学习》——多层感知机

参考资料&#xff1a; 《动手学深度学习》 4.1 多层感知机 4.1.1 隐藏层 隐藏层 激活函数能够模拟任何连续函数。 4.1.2 激活函数 4.1.2.1 ReLu函数 ReLU ⁡ ( x ) max ⁡ ( x , 0 ) \operatorname{ReLU}(x) \max(x, 0) ReLU(x)max(x,0) 当输入为负时&#xff0c;ReLU …

Python爬虫-求是网

前言 本文是该专栏的第2篇,后面会持续分享python爬虫案例干货,记得关注。 地址:aHR0cDovL3NlYXJjaC5xc3RoZW9yeS5jbi9xaXVzaGkvP2tleXdvcmQ9 需求:根据搜索关键词,爬取对应关键词下的全部文章信息 废话不多说,跟着笔者直接往下看详细内容。(附带完整代码) 正文 1. 请…

说说 OpenAI 最新发布的Function calling 是什么

这两天看的比较多的一个新闻就是 OpenAI 又更新了自己的 API。 除了各种大减价&#xff0c;增加 Token 数量之外&#xff0c;还新推出了一个叫做 Function calling 的能力。那么 Function calling 到底是什么东西&#xff0c;可能很多新闻类型的内容也没讲太明白&#xff0c;我…

基于SpringBoot+vue的教师人事档案管理系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

【力扣周赛】第 352 场周赛

文章目录 Q1&#xff1a;2760. 最长奇偶子数组解法1——纯纯暴力解法2——枚举左端点&#xff0c;尝试右端点继续优化 Q2&#xff1a;2761. 和等于目标值的质数对一个小优化 Q3&#xff1a;2762. 不间断子数组解法1——滑动窗口维护哈希表普通HashMap使用TreeMap补充&#xff1…

利用Python批量压缩图片大小(不改变图片尺寸,不改变图片格式)

我们经常需要在某些文件中如&#xff1a;Word,Excel&#xff0c;PPT等中&#xff0c;插入大量的图片&#xff0c;但是图片每一张的内存都不小&#xff0c;累计多了&#xff0c;就是导致文件的内存过大&#xff0c;导致客户打不开文件&#xff0c;那么我们可以将图片的内存压缩一…