同步机制之--java CyclicBarrier 循环栅栏
CyclicBarrier介绍
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作很有用。
CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环的barrier(栅栏)。
CyclicBarrier类似于CountDownLatch也是个计数器, 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。 CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
| 构造方法摘要 | |
|---|---|
CyclicBarrier(int parties) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每个 barrier 上执行预定义的操作。 |
|
CyclicBarrier(int parties, Runnable barrierAction) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行 |
|
| 方法摘要 | |
|---|---|
int |
await() 在所有 参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。 |
int |
await(long timeout, TimeUnit unit) 在所有 参与者都已经在此屏障上调用 await 方法之前,将一直等待。 |
int |
getNumberWaiting() 返回当前在屏障处等待的参与者数目。 |
int |
getParties() 返回要求启动此 barrier 的参与者数目。 |
boolean |
isBroken() 查询此屏障是否处于损坏状态。 |
void |
reset() 将屏障重置为其初始状态。 |
栅栏类似闭锁,但是它们是有区别的.
1.闭锁用来等待事件,而栅栏用于等待其他线程.什么意思呢?就是说闭锁用来等待的事件就是countDown事件,只有该countDown事件执行后所有之前在等待的线程才有可能继续执行;而栅栏没有类似countDown事件控制线程的执行,只有线程的await方法能控制等待的线程执行.
2.CyclicBarrier强调的是n个线程,大家相互等待,只要有一个没完成,所有人都得等着。
满足以下任何条件都可以让等待 CyclicBarrier 的线程释放:
- 最后一个线程也到达 CyclicBarrier(调用 await())
- 当前线程被其他线程打断(其他线程调用了这个线程的 interrupt() 方法)
- 其他等待栅栏的线程被打断
- 其他等待栅栏的线程因超时而被释放
- 外部线程调用了栅栏的 CyclicBarrier.reset() 方法
示例1:张孝祥视频学习笔记:
CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在i指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐……
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);// 创建CyclicBarrier对象并设置3个公共屏障点
System.out.println("创建子线程开始");
for (int i = 0; i < 3; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
Thread.sleep((long) (Math.random() * 10000));
System.out.println(
"线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1)
+ "个已到达" + (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
try {
cb.await();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
System.out.println("子线程 "+ i + "提交到线程池中");
}
System.out.println("所有子线程提交完毕,线程池关闭,但线程池关闭的真实时间为所有子线程都执行完毕后");
service.shutdown();//线程池的状态则立刻变成SHUTDOWN状态,以后不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。 与它相似的还有一个shutdownNow(),它通过调用Thread.interrupt来实现线程的立即退出。
}
}
运行结果:
创建子线程开始
子线程 0提交到线程池中
子线程 1提交到线程池中
子线程 2提交到线程池中
所有子线程提交完毕,线程池关闭,但线程池关闭的真实时间为所有子线程都执行完毕后
线程pool-1-thread-1即将到达集合地点1,当前已有1个已到达正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有2个已到达正在等候
线程pool-1-thread-2即将到达集合地点1,当前已有3个已到达都到齐了,继续走啊
线程pool-1-thread-2即将到达集合地点2,当前已有1个已到达正在等候
线程pool-1-thread-1即将到达集合地点2,当前已有2个已到达正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有3个已到达都到齐了,继续走啊
线程pool-1-thread-1即将到达集合地点3,当前已有1个已到达正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已到达正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有3个已到达都到齐了,继续走啊
示例2:并发测试时,让所有的请求在同一时间点发出去
public static void main(String[] args) throws Exception {
// cycle connect
int thread = ;
int count = ;
CyclicBarrier cyclicBarrier = new CyclicBarrier(thread + );
AtomicLong connectCount = new AtomicLong();
for (int i = ; i < thread; i++) {
new requestThread().start();
}
try {
cyclicBarrier.await();
while (true) {
System.out.println(new Date() + " Send message count : "
+ connectCount.get());
TimeUnit.SECONDS.sleep();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
同步机制之--java CyclicBarrier 循环栅栏的更多相关文章
- java并发之(4):Semaphore信号量、CounDownLatch计数锁存器和CyclicBarrier循环栅栏
简介 java.util.concurrent包是Java 5的一个重大改进,java.util.concurrent包提供了多种线程间同步和通信的机制,比如Executors, Queues, Ti ...
- 浅谈利用同步机制解决Java中的线程安全问题
我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...
- 线程工具类 - CyclicBarrier(循环栅栏)
CyclicBarrier官方文档 一.原理 CyclicBarrier是另外一种多线程并发控制实用工具.它和CountDownLatch非常类似,它也可以实现线程的计数等待,但它的功能比CountD ...
- 同步机制之--java之CountDownLatch闭锁
CountDownLatch闭锁 1.类介绍 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数初始化 CountDownLatch.CountDown ...
- Java并发编程原理与实战二十七:循环栅栏:CyclicBarrier
昨天我们学习了倒计数功能的等待,今天我们学习的是循环栅栏:CyclicBarrier.下面我们就开始吧: 1.CyclicBarrier简介CyclicBarrier,是JDK1.5的java.uti ...
- 戏说java多线程之CyclicBarrier(循环栅栏)的CyclicBarrier(int parties)构造方法
CyclicBarrier是JDK 1.5 concurrent包出现的一个用于解决多条线程阻塞,当达到一定条件时一起放行的一个类.我们先来看这样一个简单的需求. 现在我有一个写入数据的类,继承Run ...
- java高并发系列 - 第17天:JUC中的循环栅栏CyclicBarrier常见的6种使用场景及代码示例
这是java高并发系列第17篇. 本文主要内容: 介绍CyclicBarrier 6个示例介绍CyclicBarrier的使用 对比CyclicBarrier和CountDownLatch Cycli ...
- java并发:线程同步机制之计数器&Exechanger
第一节 CountDownLatch (1)初识CountDownLatch (2)详述CountDownLatch CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量. ...
- java两种同步机制的实现 synchronized和reentrantlock
java两种同步机制的实现 synchronized和reentrantlock 双11加保障过去一周,趁现在有空,写一点硬货,因为在进入阿里之后工作域的原因之前很多java知识点很少用,所以记录一下 ...
随机推荐
- PentesterLab-From SQL Injection to Shell
一.打开靶机ip出现如下界面: 随便点一下,点到test链接,访问了如下url:http://192.168.109.131/cat.php?id=1,这里出现了一个id,常规思路这个位置可能有sql ...
- Ubuntu与ROS的Docker桌面系统与ROS在线练习课程(在线Linux虚拟机)
ROS在线练习课程正在逐步完善中,目前以ROS官网中文资料制作,可参考: https://www.shiyanlou.com/courses/854 邀请码 U23ERF8H 安装Ubuntu+RO ...
- css实现加载中的效果
那天闲着,学习了一下样式效果,自己实现了一个简单的加载中的效果 废话不多说,开始吧!! 一.实现一个圆环 要实现圆环,首先我们需要知道盒模型里面border的本质,先来看一个效果吧 从上面 ...
- mailto web弹出outlook发送邮件
1. <pre name="code" class="html"><a href="Mailto:test@163.com?CC=t ...
- Extjs 5 可选择日期+时间的组件DateTimeField
我们都知道ExtJs有日期组件DateField,但直到ExtJs 5.0版本该日期组件也只能选择日期,不能选择时间(具体到时.分.秒),而实际工作中又常常会有需要日期和时间同时选择的需求,我们只能自 ...
- go语言学习 strings常用函数
strings包中的函数用法 参考链接http://studygolang.com/articles/88 1.strings.replace() 函数原型 func Replace(str1, ol ...
- python之List排序
sorted() #coding:utf-8 #sorted Ascending 升序 L = [12,23,43,3,65,34,21,3645] print(sorted(L)) >> ...
- 【剑指offer】判断一个序列是否是二叉搜索树的后序遍历,C++实现
原创文章,转载请注明出处! 本题牛客网地址 博客文章索引地址 博客文章中代码的github地址 1.题目 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出N ...
- lx 与cd 的计算方法
Candela to lux calculation with distance in meters The illuminance Ev in lux (lx) is equal to the lu ...
- Uoj 441 保卫王国
Uoj 441 保卫王国 动态 \(dp\) .今天才来写这个题. 设 \(f[u][0/1]\) 表示子树 \(u\) 中不选/选 \(u\) 时的最小权值和,显然有:\(f[u][0]=\sum ...