摘要:介绍Java中CountDownLatch的使用方法,重点包括计数器的值、countDown和await。计数器的值表示任务线程的个数,每次countDown都会使计数减一,减到0的时候调用await方法的线程就不再被阻塞。

综述

  CountDownLatch一般被称作"计数器",计数器的初始值是线程的数量,是一个同步工具类,用来协调多个线程之间的同步。其中,count down是倒数的意思,latch则是门闩的含义,整体含义可以理解为倒数的门栓;有一点“三二一,芝麻开门”的感觉。

  CountDownLatch在初始化时,需要指定一个正整数作为计数器起始值,每当一个线程执行完毕后,计数器就被countDown方法减1,当计数器为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就被唤醒,恢复工作。从线程执行状态的角度分析,就是允许一个或多个线程等待,直到其它线程执行完成才继续往下走。

  CountDownLatch是在java 1.5 被引入的,与它一起被引入的工具类还包括CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue等,它们都位于java.util.cucurrent包下。

  CountDownLatch的计数器无法被重置,当计数器被减到0时,调用await方法会直接返回。这一点有别于Semaphore,Semaphore是可以通过release操作恢复信号量的。

CountDownLatch类

  CountDownLatch 类提供了三个核心构造器:

//参数count为计数值,即线程个数
public CountDownLatch(int count) { };
/**
* Causes the current thread to wait until the latch has counted down to
* zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
*
* <p>If the current count is zero then this method returns immediately.
*
* 调用await()方法的线程会被挂起,直到count值为0才继续执行
*/
public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后,如果计数器的值还没倒数至0,就会被唤醒继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
/**
* Decrements the count of the latch, releasing all waiting threads if
* the count reaches zero.
* 每次减少一个门闩数,如果等于零,则释放等待线程
* <p>If the current count is greater than zero then it is decremented.
* If the new count is zero then all waiting threads are re-enabled for
* thread scheduling purposes.
*
* <p>If the current count equals zero then nothing happens.
*/
public void countDown() { };

  如果想使线程处于等待状态,则调用await()方法,此线程一般是主线程。温馨提示,await()方法并没有规定只能由一个线程执行,如果多个线程同时执行await()方法,那么这几个线程都将处于等待状态,并且以共享模式享有同一把锁。另外,当同一个线程多次调用countDown()方法时,每次都会使计数器减一;

  简单总结一下,CountDownLatch有三个重点:计数器的值、await、countDown。计数器的值表示任务线程的个数,每次countDown都会使计数减一,减到0的时候await方法所在的线程就不再被阻塞。

使用场景

  CountDownLatch非常适合于对任务进行拆分,使其并行执行,实现最大的并行性。某一线程A在开始运行前一直被阻塞,需等待n个其它线程执行完毕,则需将CountDownLatch的计数器初始化为 new CountDownLatch(n),每当一个任务线程执行完毕,则调用countDown()函数使得计数器减一;当计数器变为0时,在CountDownLatch上await()的线程A就会被唤醒。

  例1,会计汇总一年的财务报表时,可以把任务按照季度拆分为四份,那么就可以将这个大任务拆分为4个子任务,分别交由4个财务(线程)执行,执行完成之后再由主财务(主线程)进行财务汇总。此时,总的执行时间将决定于执行最慢的任务,通常来看,还是可以大大减少总的执行时间。

  例2,有10个线程需要加载一些资源,而另外一个线程A必须在所有资源被加载完成后才能继续执行,那么我们可以new一个CountDownLatch(10)的闭锁,每个加载资源的线程执行完后都调用countDown()函数,而线程A则在需要的资源准备齐全之前因调用await函数而被阻塞,当计数器的值为0时,线程A就会被唤醒继续执行。

知行合一

  案例如下:

结束语

  JUC CountDownLatch是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。原理:它通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就减一。当计数器递减至零时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就被唤醒,恢复执行任务。

  老铁们, 因个人能力有限,难免有瑕疵,如果发现bug或者有更好的建议,那么请在文章下方留言!

Java CountDownLatch的使用方法的更多相关文章

  1. java CountDownLatch 等待多线程完成

    CountDownLatch允许一个或多个线程等待其他线程完成操作. package com.test; import java.util.concurrent.CountDownLatch; pub ...

  2. 获取当前应用的系统路径工具类和java的System.getProperty()方法介绍

    java的System.getProperty()方法可以获取的值,如下: 对于Java程序,无论是未打包的还是打包的JAR或WAR文件,有时候都需要获取它运行所在目录信息,如何做到这一点呢? /** ...

  3. Java实现时间动态显示方法汇总

    这篇文章主要介绍了Java实现时间动态显示方法汇总,很实用的功能,需要的朋友可以参考下 本文所述实例可以实现Java在界面上动态的显示时间.具体实现方法汇总如下: 1.方法一 用TimerTask: ...

  4. Java Native Interfce三在JNI中使用Java类的普通方法与变量

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 前面我们学习了如何在JNI中通过参数来使用J ...

  5. 浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: 1 public native int hashCode(); 根据 ...

  6. 0019 Java学习笔记-面向对象-方法

    方法属于谁 方法要么属于类,要么属于对象 static修饰的方法属于类 没有static修饰的方法属于对象 方法只能定义在类里面,不能独立定义 不能独立的执行方法,要么通过类调用,要么通过方法调用 一 ...

  7. [Java] - 格式字符串替换方法

    Java 字符串格式替换方法有两种,一种是使用String.format(...),另一种是使用MessageFormat.format(...) 如下: import java.text.Messa ...

  8. atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug

    atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId&qu ...

  9. JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

  10. 千万不要误用 java 中的 HashCode 方法

    刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...

随机推荐

  1. 第二课 - 输入(按键)控制输出(LED)-设备树

    在第一课中学习了如何安装NCS开发环境,以及如何新建一个工程,还有如何构建和下载到开发板.并运行了官方的LED闪烁例程. 设备树 我们继续跟着官方开发者学院的教程来学习第二课的课程.官方课程包含了以下 ...

  2. MyCat分库分表-主从

    一.MySQL数据同步 1.主节点配置,log-bin,指定文件名称 2.主节点配置server-id,默认为1 vim /etc/my.cof 在[mysqld]下添加如下配置 log-bin=im ...

  3. 【P4】Verilog搭建单周期MIPS-CPU

    课下 Bug_Log 1.模块实例化的信号需先定义,且记得定义完备 其实testbench见过多次了,自己写的时候还想不清. 若实例化模块时使用的信号,若事先无声明,则会自动生成1bit此名称信号,自 ...

  4. 手把手教你下载b站视频并生成音频字幕

    1.下载b站视频: 可以直接使用https://bilibili.iiilab.com/ 贴进去网址就能下载了 2.提取音频 可以使用 ffmpeg 将音频文件提取出来(ffmpeg直接去官网下载即可 ...

  5. Cython二进制逆向系列(三)运算符

    Cython二进制逆向系列(三)运算符 在开始前,先给出本文用到的py源代码 def test1(x, y): # 数学运算符 a = x + y b = x - y c = x * y d = x ...

  6. PLSQL自动登录,记住用户名密码&日常使用技巧

    配置启动时的登录用户名和密码 这是个有争议的功能,因为记住密码会给带来数据安全的问题. 但假如是开发用的库,密码甚至可以和用户名相同,每次输入密码实在没什么意义,可以考虑让PLSQL Develope ...

  7. 使用LLaMA-Factory训练LLM大模型并用ollama调用

    环境搭建 系统环境 需要Nvidia显卡,至少8G显存,且专用显存与共享显存之和大于20G 建议将非安装版的环境文件都放到非系统盘,方便重装或移植 以Windows11为例,非安装环境文件都放在 E ...

  8. C#(如何解决使用enum和struct作为Dictionary的TKey带来的GC

  9. 记一次 .NET某云HIS系统 CPU爆高分析

    一:背景 1. 讲故事 年前有位朋友找到我,说他们的系统会偶发性的CPU爆高,有时候是爆高几十秒,有时候高达一分多钟,自己有一点分析基础,但还是没找到原因,让我帮忙看下怎么回事? 二:CPU爆高分析 ...

  10. 阿里云OSS前端直传

    注意: oss直传request与global对象冲突 <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-6.9.0.m ...