Java并发学习(十六)-并发工具CyclicBarrier
来源:互联网 发布:java贵美商城 编辑:程序博客网 时间:2024/06/07 08:15
What is CyclicBarrier
从名字来看,barrier:栅栏,cyclic:循环的。
简单点说,它能够让一组数量线程在某一个时间点等待,当所有线程都到了,再让它们运行。
例如有这样一个情景,有n个excel表格数据,你需要获取他们所有的数据后,再进行下一步运算。利用CyclicBarrier来做,首先需要开n个线程,等这n个线程都完成到达这个点,再进行下一步运算。
首先看它的内部构造:
CyclicBarrier结构
记得开始讲ReentrantLock的时候,说道Condition这个类,它和普通的wait和notify有区别,因为它能够唤醒一组线程,这里可以参看: Java并发学习(十二)-ReentrantLock分析 。
所以这里思路就简单了,没错,利用ReentranLock和Condition来实现。
public class CyclicBarrier { /** * 每一个barrier,都代表这一个Generation实例。当barrier损坏或者重置是,generation会改变。 */ private static class Generation { boolean broken = false; } // 利用可重入锁,reentrantlock,守护栅栏的进入 private final ReentrantLock lock = new ReentrantLock(); //等待,知道被损坏。 private final Condition trip = lock.newCondition(); //代表进入数量 private final int parties; //当所有线程到达时候,需要做的事。 private final Runnable barrierCommand; ..}
简单列举出几点:
- 从cyclic知道,一个Cyclic是可以循环使用的,就好比去银行换整钞,到100你就能换一张1百的,可以循环利用。这个是通过
Generation
这个静态内部类来实现的。 ReentrantLock
和Condition
来控制挂起以及唤醒操作。- 可以自定义
barrierCommand
,即当所有线程都到达时,先执行barrierCommand
线程,在唤醒所有等待线程。具体分到时间片则有区别。
构造方法
- CyclicBarrier(int parties):当给定数量的参与者(线程)等待它时,它将跳闸,自动唤醒所有线程并运行。
- CyclicBarrier(int parties, Runnable barrierAction):当给定数量的参与者(线程)等待它时将会跳闸,并首先执行barrierAction线程。然后唤醒其他线程,这些由最后进来的线程执行。
接下来分析等待代码。
await方法
当需要利用CyclicBarrier进行等待时候,调用await方法:
public int await() throws InterruptedException, BrokenBarrierException { try { //强行等待。不带超时 return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } }
再看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; //如果g,被破坏了,也就是为true了,那么就报错。 if (g.broken) throw new BrokenBarrierException(); //如果线程中断了。当前线程,那么也报错。 if (Thread.interrupted()) { breakBarrier(); throw new InterruptedException(); } //先自减。然后看是否需要运行command //也就是不用把最后一个也await了,直接让他运行。 int index = --count; if (index == 0) { // tripped 绊倒。 //都到了,开始运行。 boolean ranAction = false; try { final Runnable command = barrierCommand; if (command != null) command.run(); ranAction = true; //更新generation,并唤醒所有线程。 nextGeneration(); return 0; } finally { if (!ranAction) //打破栅栏,让所有线程都运行。 breakBarrier(); } } // loop until tripped, broken, interrupted, or timed out //自旋,直到到齐运行,generation被破坏,中断,或者超时。 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 { 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(); } }
代码虽长,但是理解还是比较简单的,重要注释写在代码里面了,这里讲讲具体思路:
1. 首先等待操作加锁操作。
2. 判断generation是否改变,是否中断等。
3. 将count自减操作,如果已经满足开启栅栏要求,则不对最后一个线程进行await操作,直接signalAll其他线程。
4. 检查完后,则进行自旋操作,直到到齐运行,generation被破坏,中断,或者超时。
5. 最后释放锁。
例子
public class CyclicBarrierTest { private static CyclicBarrier cyclicBarrier; static class CyclicBarrierThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + "我走完了run了"); // 等待 try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { cyclicBarrier = new CyclicBarrier(3, new Runnable() { public void run() { System.out.println("大家都走完了"); } }); for (int i = 0; i < 3; i++) { new CyclicBarrierThread().start(); } }}
输出结果如下:
参考资料:
1. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html
阅读全文
0 0
- Java并发学习(十六)-并发工具CyclicBarrier
- Java并发工具类CyclicBarrier
- java 并发工具类-CyclicBarrier
- 线程并发工具--CyclicBarrier
- java 并发工具类CyclicBarrier介绍
- Java并发工具类CountDownLatch和CyclicBarrier
- Java并发之工具类CyclicBarrier
- Java并发工具类CountDownLatch和CyclicBarrier
- Java并发工具类之CyclicBarrier
- Java并发学习笔记(四)-栅栏CyclicBarrier
- 深入学习java并发编程:CountDownLatch、CyclicBarrier
- Java并发编程--CyclicBarrier
- Java并发同步器--CyclicBarrier
- Java并发之CyclicBarrier
- Java并发之CyclicBarrier
- java并发中的CyclicBarrier
- java 并发之 CyclicBarrier
- Java并发学习之十八——线程同步工具之CyclicBarrier
- 蓝桥杯2016C语言A组赛题解析
- (作业)利用网络编程实现多个城市的天气查询
- Nfs安装配置
- C#窗体贪吃蛇
- 【Scikit-Learn 中文文档】机器学习: scikit-learn 中的设置以及预估对象
- Java并发学习(十六)-并发工具CyclicBarrier
- PhpStorm+Xampp+Xdebug搭建环境并部署应用
- EasyUI的DataGrid绑定Json数据源
- Python学习笔记
- Android开发圆形头像
- 【Scikit-Learn 中文文档】监督学习:从高维观察预测输出变量
- 图的深度优先搜索
- docker之常用命令整理
- VMware虚拟机增加磁盘空间的扩容操作