为什么80%的码农都做不了架构师?>>>   

  java.util.concurrent.CyclicBarrier也是JDK 1.5提供的一个同步辅助类(为什么用也呢?参见再谈CountDownLatch),它允许一组线程互相等待,直到到达某个临界点(a common barrier point,翻译成公共障碍点、公共栅栏点都不够传神,直接用临界点吧)。在某个程序中,一组固定大小的线程必须互相等待时,CyclicBarrier将起很大的作用。因为在等待线程被释放后,这个临界点可以重用,所以说是循环的。

  CyclicBarrier支持一个可选的Runnable,在一组线程中的最后一个线程完成之后、释放所有线程之前,该Runnable在屏障点运行一次(每循环一次Runnable运行一次)。这种方式可以用来在下一波继续运行的线程运行之前更新共享状态(比如下一波僵尸来之前,检查武器弹药)。

CountDownLatch与CyclicBarrier

  CountDownLatch是不能够重复使用的,是一次性的,其锁定一经打开,就不能够在重复使用。就像引线,点燃后就在燃烧减少,燃烧完了就不能再次使用了。CyclicBarrier是一种循环的方式进行锁定,这次锁定被打开之后,还能够重复计数,再次使用。就像沙漏,这次漏完了,倒过来接着漏。

  还有一点是两者之间很大的区别,就是CountDownLatch在等待子线程的过程中,会锁定主线程,而CyclicBarrier不会锁定主线程,只是在所有子线程结束后,根据定义执行其可选的Runnable线程。

  所以在这两种辅助类中进行选择时,能够很明显进行区分。

CyclicBarrier实例

  可以考虑这么一种情况,我们需要向数据库导入一些数据,没导入几条希望能进行一次计时,便于我们查看。因为实现比较简单,直接上代码:

package howe.demo.thread.cyclicbarrier;import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;/*** @author liuxinghao* @version 1.0 Created on 2014年9月17日*/
public class CyclicBarrierTest {public static void main(String[] args) throws InterruptedException {final long start = System.currentTimeMillis();final CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {@Overridepublic void run() {long end = System.currentTimeMillis();System.out.println("导入" + 3 + "条数据,至此总共用时:" + (end - start)+ "毫秒");}});for (int i = 0; i < 9; i++) {final int threadID = i + 1;new Thread(new Runnable() {@Overridepublic void run() {try {TimeUnit.SECONDS.sleep(new Random().nextInt(10));// 模拟业务操作System.out.println(threadID + "完成导入操作。");barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}}).start();}System.out.println("====主线程结束====");}
}

执行结果为:

====主线程结束====
4完成导入操作。
2完成导入操作。
1完成导入操作。
导入3条数据,至此总共用时:4006毫秒
5完成导入操作。
6完成导入操作。
8完成导入操作。
导入3条数据,至此总共用时:4007毫秒
3完成导入操作。
0完成导入操作。
7完成导入操作。
导入3条数据,至此总共用时:8006毫秒

  程序没导入3条会进行一次计时,统计已经执行的时间。如果CyclicBarrier构造函数的数字和for循环的次数相等的话,这个就是总共用时。

扩展

  考虑一下上面的例子,如果for循环的次数不是CyclicBarrier监听次数的整数倍,比如是10,那执行结果将会是:

====主线程结束====
2完成导入操作。
5完成导入操作。
4完成导入操作。
导入3条数据,至此总共用时:4005毫秒
8完成导入操作。
1完成导入操作。
3完成导入操作。
导入3条数据,至此总共用时:5005毫秒
7完成导入操作。
6完成导入操作。
0完成导入操作。
导入3条数据,至此总共用时:8005毫秒
9完成导入操作。

  在打印完“9完成导入操作。”之后,将一直等待。在这里可以通过barrier.getNumberWaiting()查看还差多少个线程达到屏障点。如果出现这种情况,那就需要和CountDownLatch配合使用了,当子线程全部执行完,有判断barrier.getNumberWaiting()不等于0,则调用barrier.reset()重置。这个时候将会触发BrokenBarrierException异常,但是将结束整个过程。

修改的代码如下:

package howe.demo.thread.cyclicbarrier;import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;/*** @author liuxinghao* @version 1.0 Created on 2014年9月17日*/
public class CyclicBarrierTest {public static void main(String[] args) throws InterruptedException {final long start = System.currentTimeMillis();final CountDownLatch count = new CountDownLatch(10);final CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {@Overridepublic void run() {long end = System.currentTimeMillis();System.out.println("导入" + 3 + "条数据,至此总共用时:" + (end - start)+ "毫秒");}});for (int i = 0; i < 10; i++) {final int threadID = i + 1;new Thread(new Runnable() {@Overridepublic void run() {try {TimeUnit.SECONDS.sleep(new Random().nextInt(10));// 模拟业务操作System.out.println(threadID + "完成导入操作。");count.countDown();barrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {System.out.println("触发BrokenBarrierException异常。");}}}).start();}count.await();if(barrier.getNumberWaiting() != 0) {System.out.println("不是整数倍。都已执行完,重置CyclicBarrier。");barrier.reset();}System.out.println("====主线程结束====");}
}

执行结果为:

3完成导入操作。
9完成导入操作。
6完成导入操作。
导入3条数据,至此总共用时:3005毫秒
8完成导入操作。
5完成导入操作。
10完成导入操作。
导入3条数据,至此总共用时:7005毫秒
1完成导入操作。
7完成导入操作。
4完成导入操作。
2完成导入操作。
导入3条数据,至此总共用时:9005毫秒
不是整数倍。都已执行完,重置CyclicBarrier。
====主线程结束====
触发BrokenBarrierException异常。

  使用barrier.reset()进行重置,因为CyclicBarrier是一个循环,开头就是结尾,所以重置也可以理解为直接完成。

  另外,因为使用了CountDownLatch,所以主线程会锁定,直到线程通过count.await()向下执行。

转载于:https://my.oschina.net/boltwu/blog/717344

多线程003 - 再谈CyclicBarrier相关推荐

  1. 003|再谈10000小时,三板斧破四困境 - 《硅谷来信》

    吴军老师在前面第二封信讲了有关对『一万小时定论』理解的四误区,即: 简单重复 习惯性失败 林黛玉式的困境 狗熊辦棒子 下面他分享了自己对此类误区处理的经验,并且提到,很多时候,没有绝对正确方法和错误的 ...

  2. 劫起|再谈Linux epoll惊群问题的原因和解决方案

    原作者:dog250,授权发布 重新整理: 极客重生 文章有点长,可以三连收藏慢慢看 缘起 近期排查了一个问题,epoll惊群的问题,起初我并不认为这是惊群导致,因为从现象上看,只是体现了CPU不均衡 ...

  3. 网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解

    目录 前文链接(系列助学, 也为后文学习做铺垫, 可按需读取) 一. 再谈HTTP再理解 二. HTTP对比学习HTTPS HTTP和HTTPS的区别如下: 三.TCP协议  (三次握手四次挥手细节过 ...

  4. 再谈JSON -json定义及数据类型

    再谈json 近期在项目中使用到了highcharts ,highstock做了一些统计分析.使用jQuery ajax那就不得不使用json, 可是在使用过程中也出现了非常多的疑惑,比方说,什么情况 ...

  5. C++_动态绑定,再谈const,new,delete

    C++_动态绑定,再谈const,new,delete

  6. 再谈HTTP2性能提升之背后原理—HTTP2历史解剖

    即使千辛万苦,还是把网站升级到http2了,遇坑如<phpcms v9站http升级到https加http2遇到到坑>. 因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1 ...

  7. 再谈工作的主动性和有效提问

    主动性是一个非常奇怪的词,每个人对这个词的理解都不一样.可能一个管理者对员工说,你要提高主动性,但是员工会非常苦恼,甚至崩溃:我都天天加班了,你居然还在谈提高主动性? 结合很多应届生在实际工作中遇到的 ...

  8. 再谈符号间干扰(一)

    在对话通信原理系列相关博文中,有这么一篇博文:通信系统之信道,这篇博文里面已经讲过符号间干扰(ISI),发生符号间干扰的原因在于信号带宽大于相干带宽,同一个意思的表达为:发送符号的周期小于最大时延扩展 ...

  9. 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯...

    在一个基于面向服务的分布式环境中,借助一个标准的.平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互.这个交互的过程实 ...

最新文章

  1. 如何解决MySQL order by limit语句的分页数据重复问题?
  2. C++读写txt文件方式以及基于opencv的Mat数据类型读写txt文件
  3. 通过命令行方式批量设置保留IP地址的代码
  4. 你有没有遇到要实现多种登录方式的场景丫 一起来看看咯 Spring Security 实现多种登录方式,如常规方式外的邮件、手机验证码登录
  5. JS中调用本地Winform程序并传递参数
  6. anaconda python_机器学习用Python—Python集成工具包Anaconda安装步骤
  7. Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】
  8. thinking-in-java(21)并发2
  9. poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)
  10. Jsoup根据URL加载一个Document
  11. 基于python的性能测试工具_基于 Python 的性能测试工具 locust 与 LR 的简单对比[转发]...
  12. java+mysql 基于ssm205网上购物超市系统#毕业设计
  13. Redhat注册下载Redhat Enterprise Linux Download
  14. namecheap域名解析
  15. 深入line-height,中线,基线,底线,顶线
  16. 2021-10-21 centos7+ nginx + uwsgi(包含一个配置上的天坑)
  17. 创建anaconda虚拟环境步骤
  18. 【问链财经-EOS公开课】 第十八课 史上最全EOS 资源汇总
  19. 企业搭建APP怎么正确选择云服务器配置?
  20. DPU芯片企业中科驭数加入龙蜥社区,构建异构算力生态

热门文章

  1. C# string转double,double转string
  2. Nmap个人实战总结
  3. Linux下的用户、组和权限的详细解释
  4. openssl 对文本加密解密
  5. Spring框架Runtime介绍(导包)
  6. 常见的爬虫分析库(1)-Python3中Urllib库基本使用
  7. ACM-ICPC 2018徐州网络赛-H题 Ryuji doesn't want to study
  8. golang http Specifically check for timeout error
  9. wpf Webbrowser 乱码问题及弹窗被遮挡
  10. VC中对CString 的读写(ini文件)