CountDownLatch和CycliBarrier介绍
一、CountDownLatch
它被用来同步一个或多个任务,强制他们等待其他任务完成,这就是闭锁。
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
类中只有一个构造函数,一个int类型的参数count,代表计数器。这个计数器的初始值是线程的数量,每当一个线程结束,count-1,当count==0 时,所有线程执行完毕,在闭锁上等待的线程就可以执行了。
类中还包含了三个公共方法:
public void await()
public boolean await(long timeout, TimeUnit unit)
public void countDown()
当每个任务完成时,都会调用countDown()方法。而等待问题被解决的任务在这个锁存器上调用await()方法,这个任务就相当于被挂起了直到 timeout 或 计数器为0 。
public class CountDownLatchDemo {
static final int SIZE = 5; public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
CountDownLatch countDownLatch = new CountDownLatch(SIZE);
pool.execute(new WaitTask(countDownLatch));
for (int i = 0; i < SIZE; i++) {
pool.execute(new TaskNow(countDownLatch));
}
} } class TaskNow implements Runnable {
private final CountDownLatch countDownLatch; TaskNow(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} @Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我没完事你别想跑");
//调用countDown()的方法会减少count次数直到为0,调用await的任务才能进行
countDownLatch.countDown();
}
} class WaitTask implements Runnable {
private final CountDownLatch countDownLatch; WaitTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} @Override
public void run() {
try {
//调用await的任务会被挂起
countDownLatch.await();
System.out.println("终于轮到我了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
我没完事你别想跑
我没完事你别想跑
我没完事你别想跑
我没完事你别想跑
我没完事你别想跑
终于轮到我了
二、CylicBarrier
栅栏类似于闭锁,只是要等到所有线程都到达栅栏,才能进行接下来的动作,在没到达栅栏之前先到的要等待。
构造方法
共有两个构造方法:
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
public CyclicBarrier(int parties) {
this(parties, null);
}
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程使用await()方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),用于线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景。
await()方法
线程调用await()方法表示已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await()方法,CyclicBarrier同样提供带超时时间的await和不带超时时间的await方法:
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException{...}
可以看到await方法调用了dowait()方法,dowait()方法是核心方法其内容是:如果这个线程不是最后一个到达的线程那么进行等待直到:
- 最后一个线程到达,即index == 0
- 某个参与线程等待超时
- 某个参与线程被中断
- 调用了CyclicBarrier的reset()方法。该方法会将屏障重置为初始状态
案例
public class CycliBarrierDemo { public static void main(String[] args) {
int threadCount = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
for (int i = 0; i < threadCount; i++) {
pool.execute(new Horse(cyclicBarrier, i));
}
}
} class Horse implements Runnable {
private CyclicBarrier cyclicBarrier;
private int num; public Horse(CyclicBarrier cyclicBarrier, int num) {
this.cyclicBarrier = cyclicBarrier;
this.num = num;
} @Override
public void run() {
System.out.println("马匹:" + num + "到了");
try {
cyclicBarrier.await();
System.out.println("马匹:" + num + "在等待");
TimeUnit.MILLISECONDS.sleep(2000);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("马匹到齐");
}
} 结果:
马匹:0到了
马匹:2到了
马匹:1到了
马匹:1在等待
马匹:0在等待
马匹:2在等待
马匹到齐
马匹到齐
马匹到齐
CountDownLatch和CycliBarrier介绍的更多相关文章
- CountDownLatch和CylicBarrier以及Semaphare你使用过吗
CountDownLatch 是什么 CountDownLatch的字面意思:倒计时 门栓 它的功能是:让一些线程阻塞直到另一些线程完成一系列操作后才唤醒. 它通过调用await方法让线程进入阻塞状态 ...
- Java并发之CountDownLatch工具类
一.CountDownLatch工具类介绍 CountDownLatch类是Java并发工具常用的四大工具之一,CountDownLatch允许一个或者多个线程等待其他线程完成工作.假设我们有这样的一 ...
- 对CountDownLatch的初步学习
CountDownLatch的中文翻译为"闭锁",在JDK1.5中 CountDownLatch类加入进来.为程序猿进行并发编程提供有利的帮助. 首先我们先看看JDK文档中对于Co ...
- java高级---->Thread之CountDownLatch的使用
CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生.今天我们通过一些实例来学习一下它的用法. CountDownLatch的简单使用 CountDow ...
- CountDownLatch、CyclicBarrier、Semaphore、Exchanger 的详细解析
本文主要介绍和对比我们常用的几种并发工具类,主要涉及 CountDownLatch . CyclicBarrier . Semaphore . Exchanger 相关的内容,如果对多线程相关内容不熟 ...
- 【Java线程安全】 — 常用数据结构及原理(未完结)
本文主要记录自己对于多线程安全的学习,先来记几个线程安全模型. 首先最重要的当然是volatile和AQS了: 我们知道,整个java.cuncurrent包的核心就是volatile,CAS加自旋悲 ...
- 通过一个生活中的案例场景,揭开并发包底层AQS的神秘面纱
本文导读 生活中案例场景介绍 联想到 AQS 到底是什么 AQS 的设计初衷 揭秘 AQS 底层实现 最后的总结 当你在学习某一个技能的时候,是否曾有过这样的感觉,就是同一个技能点学完了之后,过了一段 ...
- Zookeeper--0300--java操作Zookeeper,临时节点实现分布式锁原理
删除Zookeeper的java客户端有 : 1,Zookeeper官方提供的原生API, 2,zkClient,在原生api上进行扩展的开源java客户端 3, 一.Zookeeper原生API ...
- java 利用同步工具类控制线程
前言 参考来源:<java并发编程实战> 同步工具类:根据工具类的自身状态来协调线程的控制流.通过同步工具类,来协调线程之间的行为. 可见性:在多线程环境下,当某个属性被其他线程修改后,其 ...
随机推荐
- 安装pytest-allure-adaptor后,运行报错:AttributeError: module 'pytest' has no attribute 'allure'
原因:因为pytest-allure-adaptor库基本被python3放弃了,运行很不友好,反正我运行就是报错 解决方法: 先卸载:pip uninstall pytest-allure-ad ...
- 23种设计模式之适配器模式(Adapter Pattern)
适配 即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口.例如:二转换为三箱插头,将高电压转换为低电压等. 动机(Motivate): 在软件系统中,由于应用环境的变化,常常需要将“ ...
- CVPR 2019 论文解读 | 小样本域适应的目标检测
引文 最近笔者也在寻找目标检测的其他方向,一般可以继续挖掘的方向是从目标检测的数据入手,困难样本的目标检测,如检测物体被遮挡,极小人脸检测,亦或者数据样本不足的算法.这里笔者介绍一篇小样本(few ...
- c# 9.0 特性提案 简化空参数验证代码
简而言之就是将已存在的特性null参数验证,使用一个简单的语义标注进一步简化. 对于如下这段代码 // Before void Insert(string s) { if (s is null) { ...
- 死磕 java同步系列之zookeeper分布式锁
问题 (1)zookeeper如何实现分布式锁? (2)zookeeper分布式锁有哪些优点? (3)zookeeper分布式锁有哪些缺点? 简介 zooKeeper是一个分布式的,开放源码的分布式应 ...
- IDEA 学习笔记之 多线程调试
多线程调试: 在多线程调试的时候,发现一些断点会被跳过,让人很郁闷,然后上网查了下资料,发现是自己IDEA设置不对. 使用IDEA调试多线程的时候,IDEA的断点有不同的模式,只有当Thread模式下 ...
- 快学Scala 第七课 (类构造函数)
类 主构造器: class Person (var name: String){ } 主构造参数可以不带val或者var,如果没有被其他方法使用,则不保存为字段. 如果被其他方法使用,则被升格为字段, ...
- 高清屏下canvas重置尺寸引发的问题
我们知道,清空canvas画布内容有以下两个方法. 第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height) 第二种方法就是 ...
- win7环境搭建以太坊私链
如何创建私链: 创建创世配置文件: 首先需要创建一个“创世”json配置文件,此文件描述了创世区块的一些参数.下面就是文件中的内容: { "coinbase": "0x0 ...
- kettle 利用 HTTP Client 获取猫眼电影API近期上映相关信息,并解析json
前言 Kettle 除了常规的数据处理之外,还可以模拟发送HTTP client/post ,REST client. 实验背景 这周二老师布置了一项实验: 建立一个转换,实现一个猫眼API热映电影的 ...