CountDownLatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.

CountDownLatch 是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

主要方法有:

  • CountDownLatch (int count),构造一个用给定计数器初始化的CountDownLatch。构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值
  • void await (),使当前线程在锁存器倒计数至0之前一直等待,除非线程被中断。
  • boolean await (long timeout, TimeUnit unit),使当前线程在锁存器,倒计数至0之前一直等待,除非线程被中断或超出了指定的等待时间。
  • void countDwon (),递减锁存器的计数,如果计数达到0,则释放所有等待的线程。
  • long getCount (),返回当前计数。

使用场景:

在一些应用场景中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面操作。

CountDownLatch的countDown() 和 await(),前者主要倒数一次,后者是等待倒数到0,如果没有到0,就只有阻塞等待了。

  • 应用场景1:开5个多线程去下载,当5个线程都执行完了,才算下载成功。
  • 应用场景2:当用户多文件上传时,可以采用多线程上传,当多个文件都上传成功时,才算真正的上传成功。
  • 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
  • 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
  • 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
 public class Demo {

     public static void main(String[] args) throws Exception {

         CountDownLatch latch = new CountDownLatch(3);
Worker worker1 = new Worker("xiao ming", latch);
Worker worker2 = new Worker("xiao hong", latch);
Worker worker3 = new Worker("xiao wang", latch); worker1.start();
worker2.start();
worker3.start(); latch.await(); System.out.println("Main Thread End.");
} static class Worker extends Thread { private String workerName;
private CountDownLatch latch; public Worker(String workerName, CountDownLatch latch) { this.workerName = workerName;
this.latch = latch;
} @Override
public void run() { try {
System.out.println("Worker:" + workerName + " is begin.");
Thread.sleep(1000L);
System.out.println("Worker:" + workerName + " is end.");
} catch (Exception e) {
e.printStackTrace();
}
latch.countDown();
}
}
}

输出:

 Worker:xiao ming is begin.
Worker:xiao hong is begin.
Worker:xiao wang is begin.
Worker:xiao ming is end.
Worker:xiao wang is end.
Worker:xiao hong is end.
Main Thread End.

CountDownLatch 的实现原理:

CountDownLatch 的核心实现机制利用 AbstractQueuedSynchronizer 简称“AQS”的 state状态来实现Count的阻塞机制。

 public class CountDownLattch {

     /**
*CountDownLatch 的核心实现机制利用 AbstractQueuedSynchronizer 简称“AQS”的 state状态来实现Count的阻塞机制
*/ private static final class Sync extends AbstractQueuedSynchronizer { Sync(int count) {
setState(count);
} int getCount() {
return getState();
} protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
} protected boolean tryReleaseShared(int releases) {
// 覆盖"AQS"的释放状态方式,实现自己的逻辑,来消减count的线程数
for(;;) { int c = getState();
if (c == 0)
return false; int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
} } private final Sync sync;
// 利用"AQS"的state状态,来标示线程的count的数量 public CountDownLat(int count) {
this.sync = new Sync(count);
} // 利用"AQS"获得一个共享模式下的完成状态
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
} // 利用"AQS"获得一个共享模式下的完成状态,超出了指定的等待时间
public void await(int timeout, TimeUnit unit) throws InterruptedException {
sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
} // 利用"AQS"在共享模式下释放状态也就是数字减一
public void countDown() {
sync.releaseShared(1);
} // 调用"AQS"返回当前计数
public long getCount() {
return sync.getCount();
} ...
}

同步计数器 CountDownLatch的更多相关文章

  1. Java 并发同步器之CountDownLatch、CyclicBarrier

    一.简介 1.CountDownLatch是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞 ...

  2. Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析

    1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...

  3. Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier

    Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...

  4. thread_CountDownLatch同步计数器

    CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行 ...

  5. Java多线程信号量同步类CountDownLatch与Semaphore

    信号量同步是指在不同线程之间,通过传递同步信号量来协调线程执行的先后次序.CountDownLatch是基于时间维度的Semaphore则是基于信号维度的. 1:基于执行时间的同步类CountDown ...

  6. Java并发包源码学习系列:同步组件CountDownLatch源码解析

    目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void c ...

  7. JAVA并发编程之倒计数器CountDownLatch

    CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果. 我把源码中的英文注释全部删除,写上自己的注释.就剩下 70 行不到的 ...

  8. 同步辅助类CountDownLatch用法

    CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则使当前线程处于等待状态,调用countDow ...

  9. JAVA线程同步辅助类CountDownLatch

    一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达 ...

随机推荐

  1. Oracle 11g 服务启动/关闭 及 DB dump 导入

    本地启动Oracle 服务脚本 由于本地机子安装了Oracle后,会自动启动一些默认的Oracle服务,这样子会导致机子比较慢.所以需要改成手动启动/关闭服务. 即用即开,不用就关. 开启的脚本: O ...

  2. 【vue】渲染大量数据时性能优化

    对应vue渲染大量数据时可以考虑下面几点: 1. 异步渲染组件:因为组件渲染太多,影响页面的渲染时间,所有可以延迟组件渲染,可以考虑v-if处理 2. 可以使用虚拟滚动的组件:参考使用这个插件 vue ...

  3. git怎样删除未监视的文件untracked files

    # 删除 untracked files git clean -f # 连 untracked 的目录也一起删掉 git clean -fd # 连 gitignore 的untrack 文件/目录也 ...

  4. javaFX的控制台实现

    最近做了个javaFX的工具,想弄个控制台输出信息,准备用TextArea来模拟console,但直接操纵console对象的话不依赖这个项目的地方就无法输出信息到控制台了,至于log,以前弄过一个输 ...

  5. external与static的用法

    一.extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字:它告诉编译器,其声明的函数和变量可以在本函数文件或其它函数文件中使用. 1.对于extern变量来说,仅仅是一个变量的声 ...

  6. HikariCP Druid比较

    HikariCP Github地址: https://github.com/brettwooldridge/HikariCP HikariCP是数据库连接池,而且是号称史上最快的, SpringBoo ...

  7. 【easy】437. Path Sum III 二叉树任意起始区间和

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  8. openssl 1.1.1 reference

    openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...

  9. Django-视图层(view)

    视图层(view) ​ 视图函数,简称视图,本质上是一个简单的Python函数,它接受Web请求并且返回Web响应.响应的内容可以是HTML网页,重定向,404错误,图片等任何东西,但本质是返回响应对 ...

  10. STM32 USB 鼠标+键盘 串口控制

    *MOS0101000000# 鼠标左键按下 *MOS0102000000# 鼠标右键按下 *MOS0103000000# 鼠标中键按下 *MOS0100000000# 鼠标抬起 *MOS01000a ...