【Java并发编程】闭锁
(转自:https://www.cnblogs.com/xujian2014/p/5359684.html#_label5 侵删)
1、什么是闭锁?
闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流。常见类型的Synchronizer包括信号量、关卡和闭锁)。
闭锁可以延迟线程的进度直到线程线程到达终止状态。一个闭锁工作起来就像是一道大门:直到闭锁达到终点状态之前,门一直是关闭的,没有线程能够通过,在终点状态到来的时候,所有线程都可以通过。
2、应用场景
闭锁可以用来确保特定活动直到其他的活动都完成后才开始发生,比如:
- 确保一个计算不会执行,直到它所需要的资源被初始化
- 确保一个服务不会开始,直到它依赖的其他服务都已经开始
- 等待,直到活动的所有部分都为继续处理做好充分准备
- 死锁检测,可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁
3、闭锁的实现
CountDownLatch是一个同步辅助类,存在于java.util.concurrent包下,灵活的实现了闭锁,它允许一个或多个线程等待一个事件集的发生。
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数的值就会减1。当计数器值到达0时,它所表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
4、CountDownLatch原理
CountDownLatch构造函数:
CountDownLatch(int count);
构造器中计数值(count)就是闭锁需要等待的线程数量,这个值只能被设置一次。
CountDownLatch类的方法:
- void await():使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
- boolean await(long timeout, TimeUnit unit):使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
- void countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
- long getCount():返回当前计数。
- String toString():返回标识此锁存器及其状态的字符串。
与CountDownLatch第一次交互是主线程等待其它的线程,主线程必须在启动其它线程后立即调用await方法,这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
其他的N个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务,这种机制就是通过countDown()方法来完成的。每调用一次这个方法,在构造函数中初始化的count值就减1,所以当N个线程都调用了这个方法count的值等于0,然后主线程就能通过await方法,恢复自己的任务。
5、CountDownLatch使用案例
下面介绍API中推荐的一种典型的用法。
首先给出两个类,其中一组worker线程使用了两个倒计数锁存器。
第一个类是一个启动信号,在driver为继续执行worker做好准备之前,它会阻止所有的worker继续执行。
第二个类是一个完成信号,它允许driver在完成所有的worker之前一直等待。
class Driver { // ...private final static int N=10;public static void main(String[] args) throws InterruptedException {CountDownLatch startSignal = new CountDownLatch(1);CountDownLatch doneSignal = new CountDownLatch(N);for (int i = 0; i < N; ++i) // create and start threadsnew Thread(new Worker(startSignal, doneSignal)).start();doSomethingElse(); // don't let run yetstartSignal.countDown(); // let all threads proceed doSomethingElse();doneSignal.await(); // wait for all to finish }private static void doSomethingElse(){//doSomethingElse; } }
class Worker implements Runnable {private final CountDownLatch startSignal;private final CountDownLatch doneSignal;Worker(CountDownLatch startSignal, CountDownLatch doneSignal){this.startSignal = startSignal;this.doneSignal = doneSignal;}public void run(){try{startSignal.await();doWork();doneSignal.countDown();} catch (InterruptedException ex){} // return; }void doWork(){// ... } }
基于上面的模型,下面我实现了自己的应用场景:
public class CountDownLatchDemo {final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException{CountDownLatch startLatch = new CountDownLatch(1);//开始工作CountDownLatch endLatch = new CountDownLatch(2);// 两个工人的协作 Worker worker1 = new Worker("zhang san", 5000,startLatch, endLatch);Worker worker2 = new Worker("li si", 8000, startLatch,endLatch);worker1.start();// worker2.start();// startLatch.countDown(); //工作开始endLatch.await();// 等待所有工人完成工作System.out.println("all work done at " + sdf.format(new Date()));}static class Worker extends Thread{String workerName;int workTime;CountDownLatch startLatch;CountDownLatch endLatch;public Worker(String workerName, int workTime, CountDownLatch startLatch,CountDownLatch endLatch){this.workerName = workerName;this.workTime = workTime;this.startLatch=startLatch;this.endLatch = endLatch;}public void run(){try{startLatch.await(); //等待开始工作时间System.out.println("Worker " + workerName + " do work begin at "+ sdf.format(new Date()));Thread.sleep(workTime);} catch (InterruptedException e){// TODO 自动生成的 catch 块 e.printStackTrace();}finally{System.out.println("Worker " + workerName + " do work complete at " + sdf.format(new Date()));endLatch.countDown();// 工人完成工作,计数器减一 }}} }
执行的结果为:
【Java并发编程】闭锁相关推荐
- Java 并发编程系列之闭锁(CountDownLatch)
在讲闭锁之前,我们先来思考一个问题:在多线程环境下,主线程打印一句话,如何保证这句话最后(其他线程全部执行完毕)打印? 博主目前可以想到的实现方式有两种.一种是通过 join() 方法实现,另一种就是 ...
- java闭锁_【Java并发编程三】闭锁
1.什么是闭锁? 闭锁(latch)是一种Synchronizer(Synchronizer:是一个对象,它根据本身的状态调节线程的控制流.常见类型的Synchronizer包括信号量.关卡和闭锁). ...
- 闭锁java_实例讲解Java并发编程之闭锁
这篇文章主要介绍了实例讲解Java并发编程之闭锁,闭锁相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭着的,没有任何线程可以通过,当到达结束状态时,这扇门才会打开并容许所有线程通过,需要的朋友可 ...
- 【Java并发编程实战】 5.5.1章节 闭锁 CountDownLatch 实现
文章目录 1. 什么是闭锁 2. 闭锁的应用场景 3. 闭锁的实现 4. CountDownLatch原理 5. 使用案例 5.1 入门案例 5.2 复杂案例 1. 什么是闭锁 闭锁(latch)是一 ...
- Java并发编程笔记之 CountDownLatch闭锁的源码分析
转 自: Java并发编程笔记之 CountDownLatch闭锁的源码分析 JUC 中倒数计数器 CountDownLatch 的使用与原理分析,当需要等待多个线程执行完毕后在做一件事情时候 C ...
- Java并发编程实战笔记2:对象的组合
设计线程安全的类 在设计现车让安全类的过程之中,需要包含以下三步: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问策略 实例封闭 通过封闭机制与合适的加锁策略结合起来 ...
- Java并发编程—AQS原理分析
目录 一.AQS原理简述 二.自定义独占锁及共享锁 三.锁的可重入性 四.锁的公平性 五.惊群效应 AQS全称AbstractQueuedSynchronizer,它是实现 JCU包中几乎所有的锁.多 ...
- 《Java并发编程实践-第一部分》-读书笔记
大家好,我是烤鸭: <Java并发编程实战-第一部分>-读书笔记. 第一章:介绍 1.1 并发历史: 多个程序在各自的进程中执行,由系统分配资源,如:内存.文件句柄.安全证书.进程间通信方 ...
- JAVA并发编程实践笔记
2019独角兽企业重金招聘Python工程师标准>>> JAVA并发编程实践笔记 博客分类: java JAVA并发编程实践笔记 1, 保证线程安全的三种方法: a, 不要跨 ...
- Java并发编程工具类:CountDownLatch、CyclicBarrier、Semaphore
在jdk5中,java提供了一些非常有用的辅助工具类,包括CountDownLatch和CyclicBarrier(两者都可以实现线程之间的通信).Semaphore(控制方法被线程访问的数量),他们 ...
最新文章
- DFA在C#中的实现:过滤敏感词
- Pycharm快捷键及一些常用设置
- halcon的仿射变换算子的介绍
- MYSQL查询数据中通讯最多的两个人
- letcode 41. 缺失的第一个正数
- 使用response的outputstream
- 对于容斥原理反演的思考和总结
- iOS sha1加密算法
- Swift 性能相关
- 给大家推荐几位顶级Go语言专家写的公众号
- 华为Mate 30系列发布日期、地点再曝光:9月19日 慕尼黑见?
- @程序员,你的 996,可能是给公司无能的管理背锅
- 搭建深度学习推荐系统实战
- [webpack] Content not from webpack is served from “xxxx“ 并且 http://localhost:8080/ 数据为空解决方案
- 【实战模拟】使用Kali Linux进行域名解析——模拟测试
- win10任务管理器禁用_如何在Windows 10的文件资源管理器中禁用广告和通知
- 使用java计算数组方差和标准差
- jOOQ 代码生成工具的使用说明
- 计算机网络 第四章 答案(更正版)(谢希仁 第七版)
- 小陈老师、雪人 HRBUST - 1176(优先队列+)