CountDownLatch使用
分享牛原创,CountDownLatch类的使用,CountDownLatch是一个工具类,运行主线程开启子线程的时候,子线程还没有结束的时候,主线程可以一直等待,直到初始化的现成的计数器count为0,主线程就可以不用等待继续执行了。count只能在实例化CountDownLatch类的时候初始化,没有其他的办法count注入值。
下面看一下,这样三个完成之后,计数器时1,则程序就是一直等待状态。永远不会向下执行。
countDown方法,当前线程调用此方法,则计数在实例化CountDownLatch中传入的值基础上减一。
awaint方法,调用此方法会一直阻塞当前线程,不会向下执行,直到计时器的值为0的时候程序才会继续向下执行。
1.1.2. 测试
下面的程序开始测试CountDownLatch的使用。
package com.shareniu.zkTest; import java.util.concurrent.CountDownLatch; public class ShareniuDriver { private static final int N = 2; public static void main(String[] args) throws InterruptedException { CountDownLatch doneSignal = new CountDownLatch(N); for (int i = 0; i < N; ++i) // create and start threads { new Thread(new Worker(doneSignal,i)).start(); } doneSignal.await(); doSomethingElse(); // don't let run yet } private static void doSomethingElse() { System.out.println("分享牛 我在做其他事情....."); } static class Worker implements Runnable { private CountDownLatch doneSignal; private int i; public Worker( CountDownLatch doneSignal,int i) { this.doneSignal = doneSignal; this.i=i; } public void run() { try { doWork(); } catch (Exception e) { } finally { doneSignal.countDown(); } } private void doWork() { System.out.println("开始工作....."+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
上面的程序可以得出一个结论:count为0的时候,await()之后的方法才会去执行,否则一直处于等待状态。
上面的是启动2个线程,当我们把N设置为3的时候,也就是大于2的任意数的时候,启动2个线程,其他地方不变化,发现程序一直等待,不执行。这个也间接说明了,只有count为0的时候,程序才会继续走下去。
1.1.3. 工作原理
工作原理如下图所示:
1.1.4. 使用场景
程序启动的时候,根据业务开启几个线程去执行检查服务是否正常,主线程一直等待,当检查的线程都结束的时候,主线程才能去判断对应的所有的线程返回结果,检查是否正常。
比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。
具体的程序如下:
1.1.4.1. BaseHealthChecker 类,所有类的基类
package com.shareniu.zkTest; import java.util.concurrent.CountDownLatch; public abstract class BaseHealthChecker implements Runnable { private CountDownLatch latch; private String serviceName; private boolean serviceUp; public BaseHealthChecker(CountDownLatch latch, String serviceName) { this.latch = latch; this.serviceName = serviceName; } public void run() { try { verifyService(); serviceUp = true; } catch (Exception e) { e.printStackTrace(System.err); serviceUp = false; }finally{ if(latch != null) { latch.countDown(); } } } public abstract void verifyService(); public CountDownLatch getLatch() { return latch; } public String getServiceName() { return serviceName; } public boolean isServiceUp() { return serviceUp; } }
1.1.4.2. NetworkHealthChecker 类
package com.shareniu.zkTest; import java.util.concurrent.CountDownLatch; public class NetworkHealthChecker extends BaseHealthChecker { public NetworkHealthChecker(CountDownLatch latch, String serviceName) { super(latch, serviceName); } @Override public void verifyService() { System.out.println("开始检查 " + this.getServiceName()); try { Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getServiceName() + " 检查结束"); } }
1.1.4.3. CacheHealthChecker 类
package com.shareniu.zkTest; import java.util.concurrent.CountDownLatch; public class CacheHealthChecker extends BaseHealthChecker { public CacheHealthChecker(CountDownLatch latch, String serviceName) { super(latch, serviceName); } @Override public void verifyService() { System.out.println("开始检查 CacheHealthChecker" + this.getServiceName()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.getServiceName() + "CacheHealthChecker 检查结束 "); } }
1.1.4.4. 测试类
package com.shareniu.zkTest; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class AppTest { private static List<BaseHealthChecker> services; private static CountDownLatch latch; public static void main(String[] args) throws InterruptedException { latch = new CountDownLatch(2); services=new ArrayList<BaseHealthChecker>(); services.add(new CacheHealthChecker(latch, "CacheHealthChecker")); services.add(new NetworkHealthChecker(latch, "NetworkHealthChecker")); ExecutorService executor = Executors.newFixedThreadPool(services.size()); for(final BaseHealthChecker v : services) { executor.execute(v); } //等待 指导所有的线程执行完毕 latch.await(); for(final BaseHealthChecker v : services) { boolean serviceUp = v.isServiceUp(); System.out.println(v.getServiceName()+":"+serviceUp); } } }
运行结果如下所示:
开始检查 CacheHealthCheckerCacheHealthChecker
开始检查 NetworkHealthChecker
CacheHealthCheckerCacheHealthChecker 检查结束
NetworkHealthChecker 检查结束
CacheHealthChecker:true
NetworkHealthChecker:true
CountDownLatch使用的更多相关文章
- 多线程条件通行工具——CountDownLatch
CountDownLatch的作用是,线程进入等待后,需要计数器达到0才能通行. CountDownLatch(int)构造方法,指定初始计数. await()等待计数减至0. await(long, ...
- 【Java并发编程实战】-----“J.U.C”:CountDownlatch
上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...
- 同步辅助类CountDownLatch用法
CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则使当前线程处于等待状态,调用countDow ...
- 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch
java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...
- Java并发之CountDownLatch
CountDownLatch是Java concurrent包下的一个同步工具.它可以让一个(或多个)线程等待,直到其他线程中的某些操作完成. 本质上是一个信号量,我们把它比作一个有N个插销的大门,它 ...
- Java多线程之CountDownLatch学习
给出官网上的例子:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html Java中conc ...
- 【Java】JDK类 CountDownLatch
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达 ...
- 【JUC】JDK1.8源码分析之CountDownLatch(五)
一.前言 分析完了CyclicBarrier后,下面分析CountDownLatch,CountDownLatch用于同步一个或多个任务,强制他们等待由其他任务执行的一组操作完成.CountDownL ...
- java多线程等待协调工作:CountDownLatch类的高级应用
一:说明 基本上对于线程初步了解的人,都是使用synchronized来同步线程的,也确实,它也是可以满足一些常用的问题.那么我们来说一些它不能解决的问题(其实是不怎么好解决的问题,并不是真的不能解决 ...
- 【JAVA并发编程实战】4、CountDownLatch
这是一个计数锁,说白了,就是当你上锁的时候,只有计数减少到0的时候,才会释放锁 package cn.xf.cp.ch05; public class TaskRunable implements R ...
随机推荐
- 【微信小程序】对微信http请求API的封装,方便对错误码进行处理
/** * App 微信配置文件app.js * author: nujey * versions: 1.0.0 */ App({ /** * @param {Object ...
- JavaScript数据结构与算法(三) 优先级队列的实现
TypeScript方式实现源码 // Queue类和PriorityQueue类实现上的区别是,要向PriorityQueue添加元素,需要创建一个特殊的元素.这个元素包含了要添加到队列的元素(它可 ...
- [C#]200 行代码使用 C# 实现区块链
文章原文来自:Code your own blockchain in less than 200 lines of Go!,原始文章是通过 Go 语言来实现自己的区块链的,这里我们参照该文章来使用 C ...
- [SCOI 2009]windy数
Description 题库链接 找出在 \([A,B]\) 间满足相邻位差值至少为 \(2\) 的正整数个数. \(1\leq A,B\leq 2\cdot 10^9\) Solution 数位 \ ...
- bzoj 3244: [Noi2013]树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- [SDOI2009]Bill的挑战
题目描述 题解: 因为要求的T长度一定,可定义f[i][j] 为前i位状态为j的方案,can[i][j]表示第i为字母j,可行的状态 每次往后推就行了 #include <algorithm&g ...
- bzoj4361isn dp+容斥
4361: isn Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 370 Solved: 182[Submit][Status][Discuss] ...
- C语言程序设计第六次作业--循环结构(2)
(一)改错题 序列求和:输入一个正实数eps,计算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精确到最后一项的绝对值小于eps(保留6位小数). 输入输出样例: Input e ...
- Java8的重要新特性
一.Lambda表达式 java8中Lambda表达式的书写方式: (参数) -> 表达式 (参数) -> 单行语句 (参数) -> { 语句 } 1.Lambda遍历List和Ma ...
- redis中密码设置
先打开redis-server 再打开redis-cli 在redis-cli对redis进行操作 可以通过编辑redis.conf配置文件来设置密码. 1.重启Redis设置密码: 在配置文件中有个 ...