一、闭锁(Latch)

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

应用场景:

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

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

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

二、CountDownLatch

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

如上图:主线程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、模拟最大并发数的例子

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. ado.dataset

    DataSet是ADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖与数据库的独立数据集合.所谓独立,就是说,即使断开数据链路,或者关闭数据库,DataSet依然是 ...

  2. 8.1.C++ AMP简介

    C++ AMP是专为设计支持C++的异构并行模型. 全程是: Accelerator Massive Parallelism 下面是一个Vector C++ AMP的代码,通过这段代码来解释C++ A ...

  3. OpenCV2.3.1中tbb_debug.dll is missing的解决办法

    方法1:        将\opencv\build\common\tbb\ia32目录下的tbb.dll复制改名为tbb_debug.dll  方法2:        若方法1失效,请将\openc ...

  4. 教程-DelphiXE7如何调用Java Class,JAR等文件?

    源文地址:http://jingyan.baidu.com/article/e4d08ffdb61b040fd3f60d44.html 第一步,我们先在互联网上把java2pas这个工具下载下来. 下 ...

  5. JavaScript要点(十三) HTML DOM EventListener

    addEventListener() 方法 <body> <p>该实例使用 addEventListener() 方法在按钮中添加点击事件. </p> <bu ...

  6. iOS开发-分页栏和选取器的使用

    一.分页栏 创建一个新的项目,Subclass of的值选中UIViewController,然后在storyboard中删除根视图,在右下方拖出一个Tab Bar Controller 新增分页,只 ...

  7. 【转】解决HttpServletResponse输出的中文乱码问题

    http://blog.csdn.net/simon_1/article/details/9092747 首先,response返回有两种,一种是字节流outputstream,一种是字符流print ...

  8. 【47】请使用traits classes表现类型信息

    1.考虑下面的需求,对迭代器移动d个单位.因为不同类型的迭代器,能力不同,有的迭代器(vector,deque内置迭代器)可以一步到位移动到指定位置,有的迭代器(list内置迭代器)必须一步一步移动, ...

  9. 日志文件C++ 时间 文件 行数

    #include <stdio.h> #include<windows.h> #include <time.h> #define Line __LINE__ #de ...

  10. C++在使用Qt中SLOT宏须要注意的一个小细节

    大家都知道C++虚函数的机制,对于基类定义为虚函数的地方,子类假设覆写,在基类指针或者引用来指向子类的时候会实现动态绑定. 但假设指针去调用非虚函数,这个时候会调用C++的静态绑定,去推断当前的指针是 ...