Java中使用CountDownLatch进行多线程同步
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进行多线程同步的更多相关文章
- 第九节:详细讲解Java中的泛型,多线程,网络编程
前言 大家好,给大家带来详细讲解Java中的泛型,多线程,网络编程的概述,希望你们喜欢 泛型 泛型格式:ArrayList list= new ArrayList(); ArrayList list= ...
- 《Java核心技术卷一》笔记 多线程同步(底层实现)
一.锁的基本原理 多个线程同时对共享的同一数据存取 ,在这种竞争条件下如果不进行同步很可能会造成数据的讹误. 例如:有一个共享变量int sum=0, 一个线程正调用 sum+=10,另一个线程正好也 ...
- java中的CountDownLatch
闭锁是一种同步工具类,可以延迟线程的进度直到其达到终止状态.闭锁的作用相当于一扇门:在闭锁到达结束状态值钱,这扇门一直是关闭的,没有任何线程可以通过,当到大结束状态时,这扇门会打开并允许所有的线程通过 ...
- [转]关于java中的 sychronized 同步方法 与 同步块的理解
首先,需要说明一点,也是最重要的一点,无论是同步方法 还是 同步块 都是只针对同一个对象的多线程而言的,只有同一个对象产生的多线程,才会考虑到 同步方法 或者是 同步块,如果定义多个实例的同步,可以考 ...
- Java并发编程:Java中的锁和线程同步机制
锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...
- Java并发之CountDownLatch 多功能同步工具类
package com.thread.test.thread; import java.util.Random; import java.util.concurrent.*; /** * CountD ...
- Java中两种实现多线程方式的对比分析
本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...
- Java中String做为synchronized同步锁使用详解
Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...
- JAVA中的CountDownLatch、CyclicBarrier、Semaphore的简单测试
因公司需要做一个对于CountDownLatch的分享,特写了此blog. 具体细节可以参见:小结java自带的跟锁相关的一些类 在做这个分享的过程中发现了Main和junit的运行的区别,在另外一个 ...
随机推荐
- requests+正则爬取豆瓣图书
#requests+正则爬取豆瓣图书 import requests import re def get_html(url): headers = {'User-Agent':'Mozilla/5.0 ...
- Spring-cloud(四)服务发现与消费:ribbon的使用
说明: ribbon是spring-cloud中作为服务消费者的一种角色,客户端可以通过它来对服务提供者的服务进行消费, 比如本例中是服务提供者注册到注册中心,服务提供者提供了一个服务接口,返回一个h ...
- python的布尔类型与流程控制
布尔类型其实可以算是一种特殊的数字,下面是 help() 函数得到的帮助信息: bool 首先,请注意这一行:
- java面试3-对于java中值传递的理解(Hollis)
这是根据Hollis的直面java内容习得(有兴趣的可以加他微信公众号) 对于初学者来说,要理解java中的值传递很难理解,为什么说java只有值传递?那引用传递呢? java中的错误理解: 错误理解 ...
- [python]使用django快速生成自己的博客小站,含详细部署方法
前言 人生苦短,我用python 这是之前经常听到的一句笑谈.因为新公司很多业务是用的python语言,所以这几天也一直在学习python的一些东西. 作为一个之前一直java后端的开发人员,对比ja ...
- [USACO09OPEN]滑雪课Ski Lessons
题目描述 Farmer John wants to take Bessie skiing in Colorado. Sadly, Bessie is not really a very good sk ...
- ●洛谷P3242 [HNOI2015]接水果
题链: https://www.luogu.org/problemnew/show/P3242 题解: 整体二分,扫描线+树状数组. 详细的题解:http://blog.csdn.net/thy_as ...
- 51 nod 1766 树上的最远点对(线段树+lca)
1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...
- hdu 5750 Dertouzos 素数
Dertouzos Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total ...
- 2015 多校联赛 ——HDU5334(构造)
Virtual Participation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...