CountDownLatch(闭锁)

时间:2022-10-20 18:03:56

一、闭锁(Latch)

   闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成。

应用场景:

1、确保某个计算在其需要的所有资源都被初始化之后才继续执行。二元闭锁(包括两个状态)可以用来表示“资源R已经被初始化”,而所有需要R的操作都必须先在这个闭锁上等待;

2、确保某个服务在其依赖的所有其他服务都已经启动之后才启动;

3、等待直到某个操作的所有参与者都就绪在继续执行。(例如:多人游戏中需要所有玩家准备才能开始);

二、CountDownLatch

CountDownLatch是一个同步辅助类,用于允许一个或多个线程等待直到多个线程完成一组操作。CountDownLatch初始化时指定一个计数器count,当某个线程完成操作时可以调用countDown()将计数器count减一,任何线程调用CountDownLatch的await()方法都会阻塞直到count等于0。CountDownLatch(闭锁)

如上图:主线程TA初始化了一个count=3的CountDownLatch,同时启动三个线程T1,T2,T3  处理一些业务逻辑,TA调用await()方法进入阻塞直到三个线程完成操作。当T1,T2,T3完成操作时,各自调用countDown()将计数器减一,当count=0时TA才会恢复运行。

注意:CountDownLatch 的计数器Count不能重置。

CountDownLatch是一个灵活的闭锁实现,用于如下情况:允许一个或多个线程等待一个事件集的发生。闭锁的状态包括一个计数器,初始化为一个正数,用来实现需要等待的事件数。CountDown方法对计数器做减操作,表示一个事件已经发生了,而await方法等待计数器达到零,此时所有需要等待的事件已发生。如果计数器入口时值为非零,await会一直阻塞直到计数器为零,或者等待线程中断以及超时.

在完成一组正在其他线程中执行的操作之前,它允许线程一直等待。在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;这个时候就可以使用CountDownLatch。CountDownLatch最重要的方法是countDown()和await(),前者将计数器减一,后者是等待计数到0,如果没有到达0,就阻塞等待。
CountDownLatch强调的是一个线程(或多个)需要等待另外的n个线程干完某件事情之后才能继续执行。CountDownLatch 的初始阀值一旦设置就只能递减下去,无法重置

调用CountDownLatch对象的await()方法则处于等待状态,调用countDown()方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行。

 三、应用举例

1、模拟最大并发数的例子

CountDownLatch(闭锁)

CountDownLatch(闭锁)

2、有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。所以在这里用Java代码设计两个类,Worker代表工人,Boss代表老板

工人:

package LatchAndCyclicBarrier;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Work implements Runnable{
        private CountDownLatch downLatch;
        private String name;
        public Work(CountDownLatch downLatch, String name){
            this.downLatch = downLatch;
            this.name = name;
        }


        public void run() {
            this.doWork();
            try{
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            }catch(InterruptedException ie){
            }
            System.out.println(this.name + "活干完了!");
            this.downLatch.countDown();

}

private void doWork(){
            System.out.println(this.name + "正在干活!");
        }

}
老板:

package LatchAndCyclicBarrier;
import java.util.concurrent.CountDownLatch;
public class Boss implements Runnable{
        private CountDownLatch downLatch;
        public Boss(CountDownLatch downLatch){
            this.downLatch = downLatch;
        }
        public void run() {
            System.out.println("老板正在等所有的工人干完活......");
            try {
                this.downLatch.await();
            } catch (InterruptedException e) {
            }
            System.out.println("工人活都干完了,老板开始检查了!");
        }
    }
测试代码:

package LatchAndCyclicBarrier;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestLatch {
    public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();
            CountDownLatch latch = new CountDownLatch(3);
            Work w1 = new Work(latch,"张三");
            Work w2 = new Work(latch,"李四");
            Work w3 = new Work(latch,"王二");

Boss boss = new Boss(latch);

executor.execute(w3);
            executor.execute(w2);
            executor.execute(w1);
            executor.execute(boss);
            executor.shutdown();
        }
    }
执行结果:

李四正在干活!
老板正在等所有的工人干完活......
王二正在干活!
张三正在干活!
李四活干完了!
王二活干完了!
张三活干完了!
工人活都干完了,老板开始检查了!

CountDownLatch和CyclicBarrier的主要联系和区别如下:
1.闭锁CountDownLatch做减计数,而栅栏CyclicBarrier则是加计数。
2.CountDownLatch是一次性的,CyclicBarrier可以重用。
3.CountDownLatch强调一个线程等多个线程完成某件事情。CyclicBarrier是多个线程互等,等大家都完成。
4.鉴于上面的描述,CyclicBarrier在一些场景中可以替代CountDownLatch实现类似的功能。

更贴切的例子请参见:http://www.cnblogs.com/liuling/p/2013-8-20-02.html

http://suhuanzheng7784877.iteye.com/blog/1145289

CountDownLatch(闭锁)的更多相关文章

  1. 6. CountDownLatch 闭锁

    package com.gf.demo05; import java.util.concurrent.CountDownLatch; /** * CountDownLatch : 闭锁,在完成某些操作 ...

  2. juc并发工具类之CountDownLatch闭锁

    import java.util.concurrent.CountDownLatch; /** * 闭锁: 在进行某些运算时, 只有其他所有线程的运算全部完成,当前运算才继续执行(程序流中加了一道栅栏 ...

  3. 同步机制之--java之CountDownLatch闭锁

    CountDownLatch闭锁 1.类介绍 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给定的计数初始化 CountDownLatch.CountDown ...

  4. CountDownLatch闭锁

    CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完 ...

  5. 【同步工具类】CountDownLatch闭锁任务同步

    [同步工具类]CountDownLatch闭锁任务同步 转载:https://www.cnblogs.com/yangchongxing/p/9214284.html 打过dota的同学都知道,多人一 ...

  6. CopyOnWriteArrayList(写入并复制) & CountDownLatch(闭锁)

    ConcurrentHashMap: ①Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器 的性能.② ConcurrentHashMap 同步容器 ...

  7. CountDownLatch——闭锁的实现之一

    CountDownLatch实际上是一种闭锁实现.闭锁:是一种同步工具类,可以延迟线程的进度知道其到达终止状态--<Java并发编程实战>.这个怎么解释呢?简单来说,就是有1个线程需要等待 ...

  8. CountDownLatch 闭锁、FutureTask、Semaphore信号量、Barrier栅栏

    同步工具类可以是任何一个对象.阻塞队列可以作为同步工具类,其他类型的同步工具类还包括信号量(Semaphore).栅栏(Barrier).以及闭锁(Latch). 所有的同步工具类都包含一些特定的结构 ...

  9. Java并发编程笔记之 CountDownLatch闭锁的源码分析

    JUC 中倒数计数器 CountDownLatch 的使用与原理分析,当需要等待多个线程执行完毕后在做一件事情时候 CountDownLatch 是比调用线程的 join 方法更好的选择,CountD ...

随机推荐

  1. MySQL 忘记root密码解决办法

    标签:root密码不为空 概述 很多时候mysql安装完root用户的默认密码不为空,这时候就需要通过其它办法登入到mysql重置密码. 步骤 方法1:查看/root/.mysql_secret文件 ...

  2. 七 mybatis的延迟加载

    1       延迟加载 1.1     什么是延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.coll ...

  3. 目标跟踪之Lukas-Kanade光流法

    转载自:http://blog.csdn.net/u014568921/article/details/46638557 光流是图像亮度的运动信息描述.光流法计算最初是由Horn和Schunck于19 ...

  4. wordpress教程之修改上传文件大小限制

    1. 修改apache配置文件 php.ini upload_max_filesize = 64M  post_max_size = 64M  max_execution_time = 300 //上 ...

  5. iOS 在特定页面 界面旋转

    1.在AppDelegate.h 里添加标记 2.在AppDelegate.m 里添加这个方法 3.使用 [(AppDelegate*)[UIApplication sharedApplication ...

  6. python&sol;零起点(一、列表)

    python/零起点(一.列表) 列表(list)list()可以强行转换数据类型为列表,列表是可迭代对象 列表是有序的,且列表是可变的数据类型 列表中的元素可以是(字符串.整型.元祖.列表.字典.集 ...

  7. openmv扫码通信

    import sensor, image, time import json from pyb import UART sensor.reset() # 初始化相机传感器 sensor.set_pix ...

  8. 通过python-libvirt管理KVM虚拟机 源码

    版本:0.9.13 libvirt库可真是大,先看看该版本里面都有哪些类和方法,验证过的方法我会用O开头,|开头的标示还没亲自验证过. <span style="font-size:1 ...

  9. Codeforces Round &num;250 &lpar;Div&period; 1&rpar; D&period; The Child and Sequence

    D. The Child and Sequence time limit per test 4 seconds memory limit per test 256 megabytes input st ...

  10. Linux系统时间快8个小时

    1.vi /etc/sysconfig/clock   #编辑文件ZONE="Asia/Shanghai"UTC=false                          #设 ...