CountDownLatch:

  可以让一个线程等待其他线程完成了各自的工作之后再执行。比如说一个切菜,一个人切肉,都准备完毕之后才能炒肉。

构造方法:

public CountDownLatch(int count)  count等待的线程数量

关键API:

countDown()   分线程执行完减少计数

await()        主线程等待调用

使用:

package com.nijunyang.concurrent;

import java.util.concurrent.CountDownLatch;

/**
* Description:
* Created by nijunyang on 2020/5/16 13:53
*/
public class CountDownLatchTest{ private CountDownLatch countDownLatch; public CountDownLatchTest(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(2);
CountDownLatchTest countDownLatchTest = new CountDownLatchTest(countDownLatch); new Thread(()-> {
try {
countDownLatchTest.method1();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程1").start();
new Thread(()-> {
try {
countDownLatchTest.method2();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"线程2").start(); System.out.println("等待食材准备完毕...");
countDownLatch.await();
System.out.println("炒肉..."); // System.out.println("------第二次使用-----");
// new Thread(()-> {
// try {
// countDownLatchTest.method1();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// },"线程1").start();
// new Thread(()-> {
// try {
// countDownLatchTest.method2();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// },"线程2").start();
//
// System.out.println("等待食材准备完毕...");
// countDownLatch.await();
// System.out.println("炒肉..."); } private void method1() throws InterruptedException {
Thread.sleep(5000L);
System.out.println("切菜完毕...");
countDownLatch.countDown();
} private void method2() throws InterruptedException {
Thread.sleep(10000L);
System.out.println("切肉完毕...");
countDownLatch.countDown();
}
}

原理解析

1.从构造方法进去我们可以看到又是一个熟悉的Sync内部类继承了AbstractQueuedSynchronizer,入参的数量被赋值到AbstractQueuedSynchronizer的state字段。

2.await方法会去判断state是否等于0,如果不等于0,说明其他线程还没有执行完毕。就会执行doAcquireSharedInterruptibly这个方法,将当前这个调用await方法的线程入队阻塞。

(调用链:await()-sync.acquireSharedInterruptibly-sync.tryAcquireShared-doAcquireSharedInterruptibly)

3.countDown方法,每调一次就会将state的值减1,当扣减到0的时候去唤醒上面等待的主线程执行(调用链:countDown-sync.releaseShared-sync.tryReleaseShared-doReleaseShared(减到0才会执行这方法))

CyclicBarrier

篱栅,顾名思义有拦截作用。它可以让一组线程到达栅栏时被阻塞,直到最后一个线程到达,才放行通过。比如玩LOL,需要等待所有玩家进度条100%了,才能进入游戏

构造方法:

CyclicBarrier(int parties)      parties:阻塞的线程数量

CyclicBarrier(int parties, Runnable barrierAction)  parties:阻塞的线程数量  barrierAction:当最后一个线程到达是先执行这个任务,再去执行后面的流程。

关键API:

await()  到达栅栏点等待。调用次数要和入参数量一致,否则会一致阻塞的等待。

使用

package com.nijunyang.concurrent;

import java.util.concurrent.CyclicBarrier;

/**
* @author: create by nijunyang
* @date:2019/9/5
*/
public class CyclicBarrierTest implements Runnable{
private CyclicBarrier cyclicBarrier;
public CyclicBarrierTest(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "进度条100%... ");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
CyclicBarrier cyclicBarrier = new CyclicBarrier(11, new Runnable() {//11个是因为还有一个主线程也在等待
public void run() {
System.out.println("所有人进度条100%,准备开始游戏");
}
});
for (int i = 0; i < 10; i++) {
new Thread(new CyclicBarrierTest(cyclicBarrier), "线程" + i).start();
}
cyclicBarrier.await();
Thread.sleep(300);
System.out.println("开始游戏....");
} }

原理解析

1.默认每个CyclicBarrier对象有一把锁ReentrantLock和Condition

2.将构造方法的入参数量赋值到count字段中。后续都是在count字段上面进行操作。

3.await的调用会将count的数量-1,如果扣减到0.则会先执行构造方法传入的任务(如果传了),并且重置计数器刷新栅栏,将许可数据重新赋值给count字段(可以重复使用),唤醒条件等待的线程

4.如果扣减完成之后还没有到0.说明还有线程没有到达栅栏点。则进入条件队列阻塞等到,等到最后一个到达时候,才被唤醒

 两者比较

CountDownLatch和CyclicBarrier,最终实现效果看起来都差不多,都是等待分支线程执行完毕,再往下执行。然后CyclicBarrier这个可以重复使用,因为会去刷新count的数量。CountDownLatch不会重新刷新state字段的值。当第二次await执行的时候一看state是0就直接放行了,所以一个CountDownLatch对象只能使用一次。

原理上CountDownLatch是阻塞主线程,分支线线程执行完毕将state扣减到0了之后唤醒主线程去执行,CyclicBarrier则是所有线程到达栅栏点都会阻塞等待。直到后一个到达才唤醒所有的阻塞线程。

JUC(3)---CountDownLatch、CyclicBarrier和AQS的更多相关文章

  1. CountDownLatch/CyclicBarrier/Semaphore 使用过吗?

    CountDownLatch/CyclicBarrier/Semaphore 使用过吗?下面详细介绍用法: 一,(等待多线程完成的)CountDownLatch  背景; countDownLatch ...

  2. 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

    目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...

  3. CountDownLatch CyclicBarrier和 Semaphore

    CountDownLatch CyclicBarrier和 Semaphore 原理 基于AQS实现. 让需要的暂时阻塞的线程,进入一个死循环里面,得到某个条件后再退出循环,以此实现阻塞当前线程的效果 ...

  4. java 并发工具类CountDownLatch & CyclicBarrier

    一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...

  5. 【JUC】CountDownLatch

    因为在调用端的异步中,需要调用其他多个服务获取数据再汇总结果返回,所以用到了CountDownLatch CountDownLatch的概念 CountDownLatch是一个同步工具类,用来协调多个 ...

  6. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  7. 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)

    在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...

  8. 高并发第十单:J.U.C AQS(AbstractQueuedSynchronizer) 组件:CountDownLatch. CyclicBarrier .Semaphore

    这里有一篇介绍AQS的文章 非常好: Java并发之AQS详解 AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下lo ...

  9. JUC之CountDownLatch和CyclicBarrier的区别 (转)

    CountDownLatch和CyclicBarrier的功能看起来很相似,不易区分,有一种谜之的神秘.本文将通过通俗的例子并结合代码讲解两者的使用方法和区别. CountDownLatch和Cycl ...

随机推荐

  1. 深度剖析前端JavaScript中的原型(JS的对象原型)

          这张图片有点劝退了,哈哈哈~    通过原型机制,JavaScript 中的对象从其他对象继承功能特性:这种继承机制与经典的面向对象编程语言的继承机制不同.本文将探讨这些差别,解释原型链如 ...

  2. JAVA快速排序代码实现

    通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数.然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 快速 ...

  3. 立体匹配-----NCC视差匹配

    目录 一.立体匹配算法 1.立体匹配算法分类 二.NCC 视差匹配方法 1.原理 2.NCC计算公式 3.算法流程 4.代码实现     5.不同场景运行 三.结论 四.遇到的问题及解决方法 一.立体 ...

  4. python小白入门之导入指定的模块

    在python中导入模块是通过关键字import进行导入的,下面演示一下,模块的导入,指定模块别名,指定函数别名,调用模块中所有的函数运行结果:  1.模块的导入Study.py文件里面的内容是:形式 ...

  5. view-controller

    有的时候我们只想根据一个请求地址跳转到一个页面中,中间并没有任何的处理流程,这个时候创建一个 Controller 类再编写方法来跳转就显得很繁琐.这个时候我们就可以使用 view-controlle ...

  6. 2019-2020-1 20199328《Linux内核原理与分析》第二周作业

    冯诺依曼体系结构的核心是: 冯诺依曼体系结构五大部分:控制器,运算器,存储器,输入输出设备. 常用的寄存器 AX.BX.CX.DX一般存放一些一般的数据,被称为通用寄存器,分别拥有高8位和低8位. 段 ...

  7. JAVA企业级应用TOMCAT实战(一)

    一. Tomcat简介 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun和其他一些公司及个人共 ...

  8. Windows系统自带的ODBC Data Sources的配置及使用

    一直不明白ODBC是个什么东东,虽然一次次碰到,却从没用过,看Wikipedia上的描述,可以访问各种数据库.Excel.CSV等,可以剥离数据库和操作系统依赖,简直神乎其神.不过这样的描述太抽象概括 ...

  9. Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

    JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier).本贴主要说明闭锁(Latch)和栅栏(CyclicBarri ...

  10. HDU 5954 Do Not Pour Out

    #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...