同步计数器 CountDownLatch
CountDownLatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.
CountDownLatch 是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

主要方法有:
- CountDownLatch (int count),构造一个用给定计数器初始化的CountDownLatch。构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
 - void await (),使当前线程在锁存器倒计数至0之前一直等待,除非线程被中断。
 - boolean await (long timeout, TimeUnit unit),使当前线程在锁存器,倒计数至0之前一直等待,除非线程被中断或超出了指定的等待时间。
 - void countDwon (),递减锁存器的计数,如果计数达到0,则释放所有等待的线程。
 - long getCount (),返回当前计数。
 
使用场景:
在一些应用场景中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面操作。
CountDownLatch的countDown() 和 await(),前者主要倒数一次,后者是等待倒数到0,如果没有到0,就只有阻塞等待了。
- 应用场景1:开5个多线程去下载,当5个线程都执行完了,才算下载成功。
 - 应用场景2:当用户多文件上传时,可以采用多线程上传,当多个文件都上传成功时,才算真正的上传成功。
 - 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
 - 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
 - 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
 
 public class Demo {
     public static void main(String[] args) throws Exception {
         CountDownLatch latch = new CountDownLatch(3);
         Worker worker1 = new Worker("xiao ming", latch);
         Worker worker2 = new Worker("xiao hong", latch);
         Worker worker3 = new Worker("xiao wang", latch);
         worker1.start();
         worker2.start();
         worker3.start();
         latch.await();
         System.out.println("Main Thread End.");
     }
     static class Worker extends Thread {
         private String workerName;
         private CountDownLatch latch;
         public Worker(String workerName, CountDownLatch latch) {
             this.workerName = workerName;
             this.latch = latch;
         }
         @Override
         public void run() {
             try {
                 System.out.println("Worker:" + workerName + " is begin.");
                 Thread.sleep(1000L);
                 System.out.println("Worker:" + workerName + " is end.");
             } catch (Exception e) {
                 e.printStackTrace();
             }
             latch.countDown();
         }
     }
 }
输出:
Worker:xiao ming is begin.
Worker:xiao hong is begin.
Worker:xiao wang is begin.
Worker:xiao ming is end.
Worker:xiao wang is end.
Worker:xiao hong is end.
Main Thread End.
CountDownLatch 的实现原理:
CountDownLatch 的核心实现机制利用 AbstractQueuedSynchronizer 简称“AQS”的 state状态来实现Count的阻塞机制。
 public class CountDownLattch {
     /**
      *CountDownLatch 的核心实现机制利用 AbstractQueuedSynchronizer 简称“AQS”的 state状态来实现Count的阻塞机制
      */
     private static final class Sync extends AbstractQueuedSynchronizer {
         Sync(int count) {
             setState(count);
         }
         int getCount() {
             return getState();
         }
         protected int tryAcquireShared(int acquires) {
             return (getState() == 0) ? 1 : -1;
         }
         protected boolean tryReleaseShared(int releases) {
             // 覆盖"AQS"的释放状态方式,实现自己的逻辑,来消减count的线程数
             for(;;) {
                 int c = getState();
                 if (c == 0)
                     return false;
                 int nextc = c - 1;
                 if (compareAndSetState(c, nextc))
                     return nextc == 0;
             }
         }
     }
     private final Sync sync;
     // 利用"AQS"的state状态,来标示线程的count的数量
     public CountDownLat(int count) {
         this.sync = new Sync(count);
     }
     // 利用"AQS"获得一个共享模式下的完成状态
     public void await() throws InterruptedException {
         sync.acquireSharedInterruptibly(1);
     }
     // 利用"AQS"获得一个共享模式下的完成状态,超出了指定的等待时间
     public void await(int timeout, TimeUnit unit) throws InterruptedException {
         sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
     }
     // 利用"AQS"在共享模式下释放状态也就是数字减一
     public void countDown() {
         sync.releaseShared(1);
     }
     // 调用"AQS"返回当前计数
     public long getCount() {
         return sync.getCount();
     }
     ...
 }
同步计数器 CountDownLatch的更多相关文章
- Java 并发同步器之CountDownLatch、CyclicBarrier
		
一.简介 1.CountDownLatch是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞 ...
 - Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析
		
1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...
 - Java多线程-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
		
Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-从一个错误的双重校验锁 ...
 - thread_CountDownLatch同步计数器
		
CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行 ...
 - Java多线程信号量同步类CountDownLatch与Semaphore
		
信号量同步是指在不同线程之间,通过传递同步信号量来协调线程执行的先后次序.CountDownLatch是基于时间维度的Semaphore则是基于信号维度的. 1:基于执行时间的同步类CountDown ...
 - Java并发包源码学习系列:同步组件CountDownLatch源码解析
		
目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void c ...
 - JAVA并发编程之倒计数器CountDownLatch
		
CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果. 我把源码中的英文注释全部删除,写上自己的注释.就剩下 70 行不到的 ...
 - 同步辅助类CountDownLatch用法
		
CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则使当前线程处于等待状态,调用countDow ...
 - JAVA线程同步辅助类CountDownLatch
		
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达 ...
 
随机推荐
- E: Unable to locate package clang-7 E: Unable to locate package clang++-7 E: Couldn't find any package by regex 'clang++-7'
			
我的系统是Debian 9.8, 然后在装下面这两个包的时候老是提示找不到.然后再github上一问,过了几分钟就有大佬回复了,而且亲测有效 ~$ sudo apt-get -y install cl ...
 - Spring Cloud 2.x-前言
			
Spring Cloud Spring Boot 简介 模块介绍 文章列表 简介 微服务已经成为企业开发的标配,阿里的Dubbo已经被企业大规模使用,Spring Cloud作为后起之秀,同时也是 ...
 - git知识总结-1.git基础之git分布式
			
1.前言 我们在介绍git版本管理的时候,没有提到“服务器”的概念,所有的版本管理操作,都是在本地进行的.这就是git与其它版本管理工具(如CVS.SVN等)最本质的区别所在:分布式. 所谓的分布式, ...
 - windows2012服务器中安装php7+mysql5.7+apache2.4环境
			
1.下载安装apache.2.4 https://home.apache.org/~steffenal/VC14/binaries/httpd-2.4.38-win64-VC14.zip 解压到d盘的 ...
 - python学习第31天
			
# 操作系统的发展历程 # 主要的人机矛盾是什么 : CPU的使用率 # 输入\输出数据和CPU计算没有关系 # 操作系统是怎么进化的 # 传统的纸带输入 # 磁带的存储降低了输入输出数据占用的时间, ...
 - Ubuntu  VMware workstation虚拟机清理缓存文件获得更大硬盘空间
			
1 前言 VMware workstation 15 Player经常使用拖拉复制文件到虚拟机,从而导致了drag_and_drop特别大,占用了很多硬盘空间. fanbi@ubuntu:~/.cac ...
 - cocos2dx 开启控制台
			
打开 SimulatorWin.cpp 把这句启用: #define SIMULATOR_WITH_CONSOLE_AND_MENU 1 这句本来因为#define隐藏了
 - 四 Memcache
			
官网http://memcached.org 了解 cookies和session 安装memcached # yum install memcached -y 安装nc和telnet 来管理mem ...
 - linux设置环境变量(这里以hive为例给大家举例)
			
1.进入: cd /export/servers/hive/bin/ -rwxr-xr-x. 1 root root 1031 Apr 30 2015 beeline-rw-r--r--. 1 roo ...
 - php 获取用户的IP、地址、来源
			
js方法获取用户的 ip 和 地址 <script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> ...