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. vue-router动态路由 刷新页面 静态资源没有加载的原因

    在做项目的时候,发现刷新页面的时候,静态路由没有加载,度娘了一圈,终于解决了. vue-router使用history模式+使用嵌套路由: 访问路由和嵌套路由页面,显示正常,但是刷新页面的时候,嵌套路 ...

  2. Maven 本地仓库明明有jar包,pom文件还是报错解决办法

    方法一: 找到出错的jar包文件位置,删掉_maven.repositories文件 方法二: maven中的本地仓库的index索引没有更新导致 解决方案: 在eclipse中打开菜单 window ...

  3. 盒子浮动float

    一.float的基本规律 规律1: 标准流模型中的块级盒子,默认宽度100%: 而浮动的块级盒子,宽度不会自动伸展,而是由内容(文字.padding)撑开: 浮动后的行级元素,可以设置宽度高度等属性. ...

  4. [SCOI2014]方伯伯的玉米田

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  5. 模板 AC自动机

    题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...

  6. [Codeforces]852I - Dating

    题目大意:给定一棵n个点的树,每个点上有一个汉子或妹子,每人有一个权值,每次询问一条链上选出一对权值相等的男女有多少种选法.(n,q<=10^5) 做法:比较显然的树上莫队,熟悉序列莫队那套理论 ...

  7. 【BZOJ1500】【Noi2005】维修数列

    题意原题很清楚了. 解题思路:裸的平衡树操作,注意动态开点即可. 细节还是比较多的,具体参见代码吧... #include <stdio.h> #include <algorithm ...

  8. 【bzoj3173-最长上升子序列-一题两解】

    这道题不就是简单的DP吗,BZOJ在水我!不,你是错的. ·本题特点:       不断向不同位置插入数字(按数字1,2,3,4,5,6……),需要求出每一次插入后的最长上升子序列. ·分析      ...

  9. hdu 5591 BestCoder Round #65(博弈)

    题意: 问题描述 ZYBZYB在远足中,和同学们玩了一个“数字炸弹”游戏:由主持人心里想一个在[1,N][1,N]中的数字XX,然后玩家们轮流猜一个数字,如果一个玩家恰好猜中XX则算负,否则主持人将告 ...

  10. web框架和django基础(粗糙版)

    web框架本质:    浏览器:socket客户端    服务器:socket服务端        1.自己写socket服务端(最傻)        #!/usr/bin/env python    ...