文档章节

同步工具类 -- CountDownLatch

pan_1308
 pan_1308
发布于 2017/08/18 11:48
字数 1107
阅读 7
收藏 0

一、概述

CountDownLatch 是一个同步工具类,它允许一个或者多个线程一直等待,直到其他的线程执行完后,再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。

构造函数 CountDownLatch(int count) 初始一个整数值,此值是线程将要等待的操作数,这个值只能被设置一次,而且 CountDownLatch 没有提供任何机制去重新设置这个计数值。当某个线程为了想要执行这些操作而等待时,它要使用 await()方法。此方法让线程进入休眠直到操作完成。 当某个操作结束,它使用countDown() 方法来减少CountDownLatch类的内部计数器。当计数器到达0时,这个类会唤醒全部使用await() 方法休眠的线程们。

二、使用场景

开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。

三、实现

/***
 * video- conference 系统
 */
public class Videoconference implements Runnable{

	private CountDownLatch controller;
	
	public Videoconference(int num){
		controller = new CountDownLatch(num);
	}
	
	//到达
	public void arrive(String name){
		System.out.println(name + " has arrived");
		// 减少 到达 人数
		controller.countDown();
		System.out.println("Waiting for participants:"+ controller.getCount());
	}
	
	public void run() {
		// 使用 getCount() 方法来输出这次video conference的参与值的数量信息。
		System.out.println("VideoConference Initialization participants:" + controller.getCount());
		try {
			controller.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}	

		System.out.println("VideoConference: All the participants have come");
		System.out.println("VideoConference: Let's start...");

	}
}
/**
 * 这个类表示每个video conference的参与者。
 */
public class Participant implements Runnable{

	private Videoconference videoconference;
	private String name;
	
	public Participant(Videoconference videoconference, String name){
		this.videoconference = videoconference;
		this.name = name;
	}
	
	public void run() {
		 try {
			Thread.sleep(1000);
		 } catch (InterruptedException e) {
			e.printStackTrace();
		 }
		 videoconference.arrive(name); 
	}

}
public class VidoParticipantTest {

	public static final int particitorNum = 5;
	
	public static void main(String[] args) {
		// 初始化 宴会人数
		Videoconference videoconference = new Videoconference(particitorNum);
		// 宴会主线程
		Thread conferThread = new Thread(videoconference);
		conferThread.start();
		
		// 创建 参与者 线程
		for(int i=1;i<=particitorNum;i++){
			Participant participant = new Participant(videoconference, "particitor_"+i);
			Thread threadParticipantor = new Thread(participant);
			threadParticipantor.start();
		}
	}
	
}
// console结果
VideoConference Initialization participants:5
particitor_3 has arrived
particitor_1 has arrived
Waiting for participants:3
particitor_5 has arrived
Waiting for participants:2
particitor_2 has arrived
particitor_4 has arrived
Waiting for participants:1
VideoConference: All the participants have come
VideoConference: Let's start...
Waiting for participants:4
Waiting for participants:0

说明:1、初始值决定CountDownLatch类需要等待的事件的数量。

         2、await() 方法, 被等待全部事件终结的线程调用。

         3、countDown() 方法,事件在结束执行后调用。

当创建 CountDownLatch 对象时,对象使用构造函数的参数来初始化内部计数器。每次调用 countDown() 方法, CountDownLatch 对象内部计数器减一。当内部计数器达到0时, CountDownLatch 对象唤醒全部使用 await() 方法睡眠的线程们。

不可能重新初始化或者修改CountDownLatch对象的内部计数器的值。一旦计数器的值初始后,唯一可以修改它的方法就是之前用的 countDown() 方法。当计数器到达0时, 全部调用 await() 方法会立刻返回,接下来任何countDown() 方法的调用都将不会造成任何影响。

此方法与其他同步方法有这些不同:

CountDownLatch 机制不是用来保护共享资源或者临界区。它是用来同步一个或者多个执行多个任务的线程。它只能使用一次。像之前解说的,一旦CountDownLatch的计数器到达0,任何对它的方法的调用都是无效的。如果你想再次同步,你必须创建新的对象。

import java.util.concurrent.CountDownLatch;

/***示例
 * 每天起早贪黑的上班,父母每天也要上班,话说今天定了个饭店,一家人一起吃个饭,通知大家下班去饭店集合。
 * 假设:3个人在不同的地方上班,必须等到3个人到场才能吃饭,用程序如何实现呢?
 */
public class CountDownLatchTest {

	private static CountDownLatch countDownLatch = new CountDownLatch(3);
	
	public static void main(String[] args) {
		new Thread(){
			public void run() {
			   toReach("father", 1);
			   countDownLatch.countDown();
			}
		}.start();
	   
		new Thread(){
			public void run() {
				toReach("mother", 2);
				countDownLatch.countDown();
			}
		}.start();
		
		new Thread(){
			public void run() {
				toReach("me", 3);
				countDownLatch.countDown();
			}
		}.start();
		
		try {
			countDownLatch.await();
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		eat();
	}
	
	/**
	 * 各自到达所需时间
	 * @param name
	 * @param hour
	 */
	public static void toReach(String name, int hour){
		System.out.println(Thread.currentThread().getName() +"-》" +name +" 达到 需要 " + hour + " 小时...");
	}
	
	public static void eat(){
		System.out.println(Thread.currentThread().getName()+"-》都达到了,可以开吃了...");
	}
}
//console结果:
Thread-0-》father 达到 需要 1 小时...
Thread-1-》mother 达到 需要 2 小时...
Thread-2-》me 达到 需要 3 小时...
main-》都达到了,可以开吃了...

 

© 著作权归作者所有

pan_1308
粉丝 5
博文 95
码字总数 58819
作品 0
黄冈
私信 提问
加载中

评论(1)

pan_1308
pan_1308 博主
https://www.cnblogs.com/study-everyday/p/6726695.html 这篇文章讲的也不错!😊
CyclicBarrier让多线程齐步走

从JDK 1.5之后,在java.util.concurrent包下引入了好多的处理多线程的工具类,本文首先会介绍CyclicBarrier辅助工具类,其次将用CyclicBarrier工具类来完成一个实例,最后将给出CyclicBarri...

王孟君
2016/11/06
84
0
Java多线程同步工具类之CountDownLatch

  在过去我们实现多线程同步的代码中,往往使用join()、wait()、notiyAll()等线程间通信的方式,随着JUC包的不断的完善,java为我们提供了丰富同步工具类,官方也鼓励我们使用工具类来实现...

SEOwhywhy
06/28
47
0
使用Semaphore限制资源并发访问的线程数

从JDK 1.5之后,在java.util.concurrent包下引入了好多的处理多线程的工具类,本文将介绍用来控制资源同时访问个数的Semaphore工具类, 然后采用Semaphore给出一个泊车的实例,最后给出Semapho...

王孟君
2016/11/06
966
5
使用CountDownLatch协调子线程

从JDK 1.5之后,在java.util.concurrent包下引入了好多的处理多线程的工具类,本文将介绍CountDownLatch工具类,并采用这个工具类给出一个实例。 CountDownLatch工具类介绍 CountDownLatch描...

王孟君
2016/11/05
372
2
CountDownLatch使用及实现原理

CountDownLatch是Java提供的线程递减锁,为开发人员封装出来针对特殊场景使用的工具类,主要用在某一个动作的执行以来其他动作对应线程的完成。 使用步骤: 1.拿到一个CountDownLatch实例,初...

特拉仔
2018/05/07
53
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
7
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
7
0
Flutter系列之在 macOS 上安装和配置 Flutter 开发环境

本文为Flutter开发环境在macOS下安装全过程: 一、系统配置要求 想要安装并运行 Flutter,你的开发环境需要最低满足以下要求: 操作系统:macOS(64位) 磁盘空间:700 MB(不包含 IDE 或其余...

過愙
昨天
6
0
OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
昨天
2.7K
16
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
昨天
42
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部