CountDownLatch介绍

在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法:

1、synchronized关键字进行同步。

2、Lock锁接口及其实现类ReentrantLock、ReadWriteLock锁实现同步。

3、信号量Semaphore实现同步。

其中,synchronized关键字和Lock锁解决的是多个线程对同一资源的并发访问问题。信号量Semaphore解决的是多副本资源的共享访问问题。

今天,来学习一下Java中的另外一个多线程同步辅助类:CountDownLatch。官方文档对CountDownLatch的解释是:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。也就是说,CountDownLatch控制某个或者多个线程,让它们等待多个线程完成某项任务后,再启动。CountDownLatch主要是用来同步多个任务的执行,区别于其他的synchronized关键字,锁,信号量是用来同步共享资源的。

CountDownLatch实现原理简介:

CountDownLatch内部维护一个计数器,计数器的值为待完成的任务数N,需要等待这N个任务完成的线程调用CountDownLatch的await()方法使自己进入休眠等待状态。

当某一个任务线程完成某一个任务后调用CountDownLatch的countDown()方法来表示自己的任务已完成,此时CountDownLatch的计数器值减1,当所有的任务完成式,计数器的值为0。当计数器值为0时,CountDownLatch将唤醒所有因await()方法进入休眠的线程。

CountDownLatch的使用:

CountDownLatch的使用主要有3点:

1、CountDownLatch的声明及初始化,在初始化时需要指定等待完成的任务数。

2、某一个任务完成时调用CountDownLatch的countDown()方法,向CountDownLatch报告自己的任务已经完成,

3、需要等待任务完成的线程调用CountDownLatch的await()方法,调用后该线程将进入休眠,并在所有任务数完成后CountDownLatch的计数器值为0时,因await()方法进行休眠的线程将被唤醒。

在此本人在Java 7并发编程实战手册该书中的CountDownLatch使用示例的基础上做了部分改进,来演示CountDownLatch的使用详情:

模拟10个参会者和一个主持人参加的一个会以,每个参会者及主持人需要等待其他的参会者均到场签到之后,才能开始会以并发言。为此,先创建一个会以管理的类VideoConference,其提供一个arrive()方法供参会者调用来进行签到。会议管理的拥有者是主持人,其等待每个参会者的签到:

public class VideoConference implements  Runnable{
private final CountDownLatch countDownLatch;
private int number;
public VideoConference(int number) {
this.number = number;
this.countDownLatch = new CountDownLatch(number);//使用Number初始化其内部的计数器,当初始化完成后,不能再次初始化
}
public void arrive(String name){
//每个需要同步的任务,在任务完成时,需要调用该方法
countDownLatch.countDown();//countDownLatch内部的计数器减1
System.out.print("arrive:"+name+"\n");
try{
countDownLatch.await();//await方法是线程进入休眠,当countDownLatch计数器为0时,将被唤醒
//线程被唤醒,在这里可以执行一系列任务
System.out.print("name:"+name + " say:let's start..." +"\n");
}catch (InterruptedException e){
e.printStackTrace();
}
}
public void run(){
System.out.print("has arrive:"+(number-countDownLatch.getCount())+"\n");
try{
countDownLatch.await();//await方法是线程进入休眠,当countDownLatch计数器为0时,将被唤醒
//线程被唤醒,在这里可以执行一系列任务
System.out.print("all arrived:"+(number-countDownLatch.getCount())+"\n");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}

创建一个参会者类Participant:

public class Participant implements  Runnable{
private VideoConference videoConference;
private String name; public Participant(String name, VideoConference videoConference) {
this.name = name;
this.videoConference = videoConference;
}
public void run(){
try {
//do something
Thread.sleep(50);
//
videoConference.arrive(name);
}catch (InterruptedException e){
e.printStackTrace();
}
} public static void main(String[] args){
VideoConference videoConference = new VideoConference(10);
Thread videoThread = new Thread(videoConference);
videoThread.start();
for(int i=0; i<10; i++){
Thread thread = new Thread(new Participant("participant:"+i,videoConference));
thread.start();
}
}
}

Participant类中的main函数首先创建了一个需要10个参会者参加的一个会议,之后,创建了10个参会者并逐个签到,在10个参会者都签到之后,每个参会者及主持人将被"唤醒"并发言。

总结:

CountDownLatch类解决的是多线程间的同步等待、任务协调问题,应用在如在启动某个程序的主功能前,需要前置完成配置环境检查、网络检查等多个子任务等类似的场景。在Java中,除了使用CountDownLatch来实现多线程间的同步等待以外,还可以使用栅栏技术CyclicBarrier来实现多线程间的同步等待、任务协调。

Java中使用CountDownLatch进行多线程同步的更多相关文章

  1. 第九节:详细讲解Java中的泛型,多线程,网络编程

    前言 大家好,给大家带来详细讲解Java中的泛型,多线程,网络编程的概述,希望你们喜欢 泛型 泛型格式:ArrayList list= new ArrayList(); ArrayList list= ...

  2. 《Java核心技术卷一》笔记 多线程同步(底层实现)

    一.锁的基本原理 多个线程同时对共享的同一数据存取 ,在这种竞争条件下如果不进行同步很可能会造成数据的讹误. 例如:有一个共享变量int sum=0, 一个线程正调用 sum+=10,另一个线程正好也 ...

  3. java中的CountDownLatch

    闭锁是一种同步工具类,可以延迟线程的进度直到其达到终止状态.闭锁的作用相当于一扇门:在闭锁到达结束状态值钱,这扇门一直是关闭的,没有任何线程可以通过,当到大结束状态时,这扇门会打开并允许所有的线程通过 ...

  4. [转]关于java中的 sychronized 同步方法 与 同步块的理解

    首先,需要说明一点,也是最重要的一点,无论是同步方法 还是 同步块 都是只针对同一个对象的多线程而言的,只有同一个对象产生的多线程,才会考虑到 同步方法 或者是 同步块,如果定义多个实例的同步,可以考 ...

  5. Java并发编程:Java中的锁和线程同步机制

    锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...

  6. Java并发之CountDownLatch 多功能同步工具类

    package com.thread.test.thread; import java.util.Random; import java.util.concurrent.*; /** * CountD ...

  7. Java中两种实现多线程方式的对比分析

    本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...

  8. Java中String做为synchronized同步锁使用详解

    Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...

  9. JAVA中的CountDownLatch、CyclicBarrier、Semaphore的简单测试

    因公司需要做一个对于CountDownLatch的分享,特写了此blog. 具体细节可以参见:小结java自带的跟锁相关的一些类 在做这个分享的过程中发现了Main和junit的运行的区别,在另外一个 ...

随机推荐

  1. jacascript 滚动 scroll 与回到顶部

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 滚动 scroll scrollHeight 表示元素的总高度,包括由于溢出而无法展示在网页的不可见部分: ...

  2. Testlink1.7.5安装部署

    Testlink1.7.5安装部署 1   下载安装wamp5:下载地址:http://www.duote.com/soft/56016.html wamp5是apache.mysql.PHP的集成环 ...

  3. .NET MD5 加密

    using System; using System.Security.Cryptography; using System.Text; namespace Md5Demo { /// <sum ...

  4. MariaDB表表达式(2):CTE

    本文目录: 1.非递归CTE 2.递归CTE 2.1 语法 2.2 递归CTE示例(1) 2.3 递归CTE示例(2) 2.4 递归CTE示例(3) 公用表表达式(Common Table Expre ...

  5. [LeetCode] Longest Uncommon Subsequence II 最长非共同子序列之二

    Given a list of strings, you need to find the longest uncommon subsequence among them. The longest u ...

  6. mysql 免安装与 忘记root密码 密码过期

    免安装: 参考 :https://blog.csdn.net/werwqerwerwer/article/details/52919939 注:别忘了配置环境变量   忘记root密码解决办法: 1. ...

  7. PHP观察者模式与Yii2.0事件

    1.先看PHP观察者模式的实现: 想要使用事件.必须实现事件的基类.统一的addObserver和trigger方法 定义统一接口.所有的观察者都要实现此接口 //事件的基类 abstract cla ...

  8. php文件包含漏洞(input与filter)

    php://input php://input可以读取没有处理过的POST数据.相较于$HTTP_RAW_POST_DATA而言,它给内存带来的压力较小,并且不需要特殊的php.ini设置.php:/ ...

  9. NPM实用指北

    npm作为下载node附送的大礼包,大家一定不会陌生. 然而关于npm,估计大量的只是用到npm install XXX以及npm run XXX. 其实这里边还有很多有意思的命令&参数.关于 ...

  10. [HNOI 2004]敲砖块

    Description 在一个凹槽中放置了 n 层砖块.最上面的一层有n 块砖,从上到下每层依次减少一块砖.每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示. 14 15 4 3 23 3 ...