Java多线程下循环计数器

本文主要内容:CyclicBarrier(下文中凯哥就用cycBar来代替)定义介绍;举例说明;代码演示;从源码来看原理及总结;CyclicBarrier与CountDownLatch(下文就用CountDown来代替)比较。

本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《并发工具类》教程的第二篇:《Java多线程下循环计数器》。

编辑

一:CyclicBarrier是什么

cycBar是什么呢?

来看看JDKAPI文档中是怎么介绍这个对象的:

翻译后大概意思:允许一组线程全部等待彼此达到共同的屏障点的同步辅助。循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。

有没有这种感觉:每个汉字都认识,但是放在一起就不知道什么意思了?对!没错,就是这种感觉~~~///(^v^)\\\~~~。上面翻译简单一句话就是:有个可以循环利用的集合点。作用就是让所有线程都到达这个集合点后,才会继续下一步行动。如果还是不理解,请看下下面生活中的例子。

二:CyclicBarrier生活中例子理解

在生活中,如果我们跟团旅游的话,就更容易理解了。假设一个团有7个人,旅游团安排的旅游路线是八达岭长城故宫这个路线的一日游。游玩时间是3小时。三个小时后, 统一都到八达岭的集合点:入口处。点名等人员都到齐后,发车到下一个景点。这种场景相信大家都遇到过吧。八达岭入口的集合点不仅仅这个旅游团可以使用,其他的旅游团都可以使用的。如果站在多线程并发场景下来分析的话:旅游团中每个成员都是一个线程,入口集合点就是屏障(Barrier),每个成员都必须到达集合点(循环到达Cyclic)且人数和旅游团人数相等的时候,才能触发旅游车发车去下一个景点的线程。

还有一个例子更容易理解:集齐七龙珠,召唤神龙。相信看过《七龙珠》的都知道这个吧。想要召唤神龙的触发点就是集齐七个龙珠。

通过上面案例,大家是不是更容易理解了?下面凯哥(kaigejava)将通过代码实现集齐七龙珠召唤神龙的操作。

三:代码演示

需求:集齐七颗龙珠,召唤神龙。

3.1:未使用cycbarr的时候

使用七个线程,来代替找龙珠的七个任务。每个线程在找龙珠的时候,耗时2s.就sleep。最后,七个线程执行完成之后,使用召唤神龙的线程来召唤神龙。代码如下图:

运行结果:

我们发现,龙珠还没有找到呢,神龙就出现了。这个当然是不对的。所以不使用cycBarr这个操作是不对的。

3.2:使用cycbarr

查看运行结果:

当七颗龙珠都找到之后,才可以召唤神龙。 符合我们的需求。那么,cycbarr的实现原理是什么呢?接下来我们从源码来看看运行原理。

四:从源码来看原理及总结

4.1:构造器

有两个构造器,给定一个int的parties和两个参数的构造器。参数含义:

Int parties:给定参与的线程的个数。也可以理解为屏障的值,当达到这个值之后,屏障将会跳闸执行其他任务(在集齐龙珠案例中,可以理解为需要7个线程来执行。);

Runnable barrierAction:这个参数意思是指当线程达到屏障数量后,屏障跳闸后执行给定线程的任务(在集齐龙珠案例中,可以理解为当集齐七颗龙珠后,需要执行召唤神龙的操作)。

4.2:几个重要的成员属性

其中使用了ReentrantLock这个可重入锁作为并发的锁对象。使用Codition这个对象来实现等待/通知模式。

4.3:重要方法

无论是await()还是await(long timeout,TimeUnit unit)这两个await最后都是调用dowait()方法。

Dowait方法主要干了什么?其实逻辑处理比较简单的。如果当前线程不是最后一个调用await方法的线程,则会一直自旋等待着。源码如下:

当发生以下清空的时候,就会在自旋等待了:

1:当前执行的线程是最后一个线程。即index == 0成立的时候;

2:当参与其中的某个线程在等待的时候,等待超时了;

3:参与的线程中某一个线程被中断了;

4:在调用了CycBarr的reset方法后。该方法将会将对应的屏障(parties)重置为初始状态。

对应源码如下:

4.4:总结

语法:

默认使用两个参数的构造器。然后再try代码块中调用await方法。如下图:

五:CyclicBarrier与CountDownLatch比较

关于CountDownLatch的相关介绍,凯哥(kaigejava)在另一篇文章《Java多线程并发容器之并发倒计时器》中做了详细介绍。欢迎大家去查看.

CountDown:

计数器只能够使用一次;

参与的线程的职责是不一样的(火箭发射,不同部门做的事情不一样)。有的再倒计时,有的再等待倒计时结束。

CycBarr:

是可以循环利用的,因为可以使用reset方法将屏障重置,可以使用多次,所有cycBar能够处理更为复杂的场景;

参与的线程职责是一样的(都是找龙珠);

提供了其他的方法。如获取当前阻塞的线程数量的getnumberWaiting方法。用于判断当前线程阻塞的线程是否被中断的isBroken方法。

从唤起阻塞线程角度来看的话:

CountDownLatch运行一个或者是多个线程等待一组事件的产生,而CyclicBarrier用于等待其他线程运行到屏障(栅栏)位置。

从适用场景角度来说:

CycBarr适用于多个线程结果元素的合并操作。

如需要从多个excel中统计数量的时候,可以使用CycBarr来从不同的excel读取到数据之后,在进行汇总操作。

​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​欢迎来聊

Java多线程工具类之循环栅栏计数器的更多相关文章

  1. 线程工具类 - CyclicBarrier(循环栅栏)

    CyclicBarrier官方文档 一.原理 CyclicBarrier是另外一种多线程并发控制实用工具.它和CountDownLatch非常类似,它也可以实现线程的计数等待,但它的功能比CountD ...

  2. 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

    1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...

  3. 基于AQS实现的Java并发工具类

    本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...

  4. Java并发工具类 - CountDownLatch

    Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http: ...

  5. Java 文件下载工具类

    Java 文件下载工具类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static Logger logger = ...

  6. Java Properties工具类详解

    1.Java Properties工具类位于java.util.Properties,该工具类的使用极其简单方便.首先该类是继承自 Hashtable<Object,Object> 这就奠 ...

  7. Java json工具类,jackson工具类,ObjectMapper工具类

    Java json工具类,jackson工具类,ObjectMapper工具类 >>>>>>>>>>>>>>> ...

  8. Java日期工具类,Java时间工具类,Java时间格式化

    Java日期工具类,Java时间工具类,Java时间格式化 >>>>>>>>>>>>>>>>>&g ...

  9. MinerUtil.java 爬虫工具类

    MinerUtil.java 爬虫工具类 package com.iteye.injavawetrust.miner; import java.io.File; import java.io.File ...

随机推荐

  1. 无刷新上传图片,ajax 和 iframe

    iframe 上传 upload.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ...

  2. 测试 - 某网站ACCESS数据库注入漏洞

    元宵节 团团圆圆总少不了一篇文  测试是否有注入 测试数据库类型 后面不用注释猜到可能是access 验证一下 这里说一下MySQL和ACCESS以及MSSQL的判断语句 MySQL:and len ...

  3. opt目录

    在linux环境测试时,会部署到/opt目录下,这是为何呢? 下面来详解Linux的/opt目录: /opt:用户级的程序目录 这里主要存放那些可选的程序. 比如,你想部署firefox测试版,那就装 ...

  4. C++ 小练习,一个整型数字的处理

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> //输入一个任意位数的int整数,并判断该整数的位数,并输出每一位数(每个数字中间用空 ...

  5. vue2.0:项目开始,首页入门(main.js,App.vue,importfrom)

    对main.js App.vue 等进行操作: 但是这就出现了一个问题:什么是main.js,他主要干什么用的?App.vue又是干什么用的?main.js 里面的import from又在干嘛?ne ...

  6. go入门二

    一.流程控制 1.选择结构 if-else: package main import ( "io/ioutil" "fmt" ) func main(){ co ...

  7. Java注解 看这一篇就够了

    注解 1.概念 注解:说明程序的.给计算机看的 注释:用文字描述程序的.给程序员看的 注解的定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性 ...

  8. Git&Github入门

    Github: 仓库repository: 存放项目代码,每个项目对应一个项目 收藏star: 收藏 复制克隆项目(Fork): 发起请求Pull Reques: 别人改进你的代码,如果觉得不错可以合 ...

  9. 【转】不怕难之BlockingQueue及其实现

    1. 前言 BlockingQueue即阻塞队列,它是基于ReentrantLock,依据它的基本原理,我们可以实现Web中的长连接聊天功能,当然其最常用的还是用于实现生产者与消费者模式,大致如下图所 ...

  10. Linux篇001——打开vi默认显示行号

    $ vi ~/.vimrc 新增一行命令 :set number 保存退出,source ~/.vimrc