CyclicBarrier底层实现和原理
官网解释:
- 允许一组线程全部等待彼此达到共同屏障点的同步辅助。循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。
意思就是每个线程都得执行到等待点进行等待,直到所有线程都执行到等待点,才会继续往下执行。相当于日常开会,只有等每个参会的人都到之后才会开始会议。
用法:(以开会举例)
1、会议需要三个人
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {@Overridepublic void run()2、这是三个人都到齐之后会执行的代码System.out.println("三个人都已到达会议室")}});3、定义三个线程,相当于三个参会的人for (int i = 0; i < 3; i++) {final int finalI = i;new Thread(new Runnable() {@Overridepublic void run() {try {4、模拟每人到会议室所需时间 Thread.sleep((long) (Math.random()*5000));} catch (InterruptedException e) {e.printStackTrace();}System.out.println("第"+Thread.currentThread().getName()+"个人到达会议室");try {5、等待其他人到会议室 cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"开始开会");}}, String.valueOf(finalI)).start();}
上述代码运行的结果为:
源码解析:
一、构造方法
有两个构造方法,只有带Runnable参数的构造方法才会在所有线程都到达等待点之后执行Runnable里面的run方法。
CyclicBarrier(int parties) {this(parties, null);
}CyclicBarrier(int parties, Runnable barrierAction) {if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;
}
二、维护锁状态逻辑
其底层使用ReentrantLock+Condition进行锁状态的维护
1、维护锁状态
private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();
2、线程组数
private final int parties;
3、所有线程到达等待点后执行的Runnable
private final Runnable barrierCommand;
4、需要等待的线程数量
private int count;
6、屏障点定义
private static class Generation {boolean broken = false;
}
具体看看其是如何实现等待逻辑的,线程等待需要调用await方法
public int await() {return dowait(false, 0L);}public int await(long timeout, TimeUnit unit){return dowait(true, unit.toNanos(timeout));
}
最终调用的是dowait方法
private int dowait(boolean timed, long nanos){final ReentrantLock lock = this.lock;1、获取锁lock.lock();try {final Generation g = generation;if (g.broken)throw new BrokenBarrierException();2、如果线程中断,重置等待线程数量并且唤醒当前等待的线程 if (Thread.interrupted()) {breakBarrier();throw new InterruptedException();}3、等待线程数减1int index = --count;4、当等待线程数为 时if (index == 0) { // trippedboolean ranAction = false;try {5、执行所有线程都到达等待点之后的Runnable final Runnable command = barrierCommand;if (command != null)command.run();ranAction = true;6、唤醒所有线程并生成下一代 nextGeneration();return 0;} finally {if (!ranAction)breakBarrier();}}7、如果等待线程数不为0for (;;) {try {8、根据传入的参数来决定是定时等待还是非定时等待if (!timed)trip.await();else if (nanos > 0L)nanos = trip.awaitNanos(nanos);} catch (InterruptedException ie) {9、线程中断之后唤醒所有线程并进入下一代if (g == generation && ! g.broken) {breakBarrier();throw ie;} else { Thread.currentThread().interrupt();}}10、如果线程因为打翻屏障操作而被唤醒则抛出异常if (g.broken)throw new BrokenBarrierException();11、如果线程因为换代操作而被唤醒则返回计数器的值if (g != generation)return index;12、如果线程因为时间到了而被唤醒则打翻栅栏并抛出异常if (timed && nanos <= 0L) {breakBarrier();throw new TimeoutException();}}} finally {lock.unlock();}}
可以看到,是通过index字段控制线程等待的,当index不为0的时候,线程统一会进行阻塞,直到index为0的时候,才会唤醒所有线程,这时候所有线程才会继续往下执行。
三、重复使用
这个跟CountdownLatch不一样的是,CountdownLatch是一次性的,而CycliBarrier是可以重复使用的,只需调用一下reset方法。
public void reset() {final ReentrantLock lock = this.lock;lock.lock();try {1、破坏当前的屏障点并唤醒所有线程 breakBarrier(); 2、生成下一代nextGeneration(); } finally {lock.unlock();}
}private void breakBarrier() {generation.broken = true;将等待线程数量重置count = parties;唤醒所有线程 trip.signalAll();
}private void nextGeneration() {唤醒所有线程trip.signalAll();将等待线程数量重置count = parties;generation = new Generation();
}
上述就是对CycliBarrier的解析。
CyclicBarrier底层实现和原理相关推荐
- go底层系列-defer原理剖析
go底层系列-defer原理剖析 目录 go底层系列-defer原理剖析 defer 前言 热身 defer规则 规则一:延迟函数的**参数在defer语句出现时就已经确定下来**了 规则二:延迟函数 ...
- currenthashmap底层的CAS原理
currenthashmap底层的CAS原理 介绍CAS CAS的全称是Compare And Swap 即比较交换,其算法核心思想如下 如果V值等于E值,则将V的值设为N.若V值和E值不同,则说明已 ...
- JUC多线程:CountDownLatch、CyclicBarrier、Semaphore同步器原理总结
一.CountDownLatch: 1.什么是 CountDownLatch: CountDownLatch,闭锁,就是一个基于 AQS 共享模式的同步计数器,它内部的方法都是围绕 AQS 实现的.主 ...
- .NET Micro Framework动态调用C/C++底层代码(原理篇)
.NET Micro Framework和WinCE系统不同,从应用开发角度来说,仅支持C#开发(从V4.2版本开始,才支持VB.NET开发),而不像WinCE应用开发,既可以用C#/VB.Net,也 ...
- Java集合,ConcurrentHashMap底层实现和原理(常用于并发编程)
为什么80%的码农都做不了架构师?>>> 概述 ConcurrentHashMap常用于并发编程,这里就从源码上来分析一下ConcurrentHashMap数据结构和底层原理. ...
- 阿里P8架构师谈:深入探讨HashMap的底层结构、原理、扩容机制
摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型. 随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化, ...
- HashMap底层实现及原理
注意:文章的内容基于JDK1.7进行分析.1.8做的改动文章末尾进行讲解. 一.先来熟悉一下我们常用的HashMap: 1.HashSet和HashMap概述 对于HashSst及其子类而 ...
- 【Java基础】HashMap底层数据结构及其原理
1.简单了解一下HashMap HashMap 就是以 Key-Value 键值对的方式进行数据存储的一种数据结构,它在 JDK 1.7 和 JDK 1.8 中底层数据结构是有些不一样的.简单来说,J ...
- 微信小程序底层框架实现原理
小册介绍 小程序(Mini Program)我们都很熟悉,它是一种不用下载安装就能使用的应用,它实现了应用"触手可及"的梦想.如今,微信已经把小程序打造成了新的开发者生态,而小程序 ...
最新文章
- .NET2.0抓取网页全部链接【月儿原创】
- Can't call rollback when autocommit=true
- 360下载的mysql_MySQL数据库5.7
- python集合应用场景_十、python 集合的定义与使用
- 前端学习(1928)vue之电商管理系统电商系统之美化一层循环的UI结构for循环ui美化
- Linux bunzip2命令:bz2格式的解压缩命令
- 安卓应用安全指南 4.2.1 创建/使用广播接收器 示例代码
- mysql 绑定 cpu 节点_MySQL Cluster(MySQL集群)配置
- 聊聊你们关心的视频号
- LINUX安装C#开发环境
- NClay框架AOP功能简介
- 朗格Lange 1古董车展特别版表落谁家?法拉利 335 Sport非常合衬
- Linux下使用php实现office转PDF
- 微商史上最全软文标题写作套路(收藏版)
- argis加载tpk离线包
- 阿里 P10 是怎样的存在?
- java静态网页_【屌炸天源码分享】《企业网站html静态网页模板》
- 苹果收取30%过路费_你是顶是踩?
- WPF编程,使用字体图标的一种方法。
- [Unity3D]用C#在unity里面写一个简单的红绿灯
热门文章
- Python之快速排序算法实现(二)
- Leetcode每日一题:20.valid-parentheses(有效的括号)
- Java虚拟机(四)——类加载机制
- 机器学习-吴恩达-笔记-12-推荐系统
- JS基础入门篇(四)—this的使用,模拟单选框,选项卡和复选框
- 第十五:Pytest-html报告修改与汉化
- vba 保存word里面的图片_笔记7 【office精华课】一套课程学会Word+Excel+PPT(一)【Word】(2020年第37周 周五)...
- java 关闭阻塞线程池_如果优雅地关闭ExecutorService提供的java线程池
- Linux根据启动程序文件名称进行批量结束任务
- [Spring Boot核心功能]1. SpringApplication 启动引导类(2)