CountDownLatch 计数器
这里我暂时只讲CountDownLatch的作用和怎么使用,至于他是怎么实现这种功能的,涉及源码,以后我再补上。
正文
什么是CountDownLatch?
CountDownLatch是在java1.5被引入,存在于java.util.cucurrent包下。CountDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
他是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
为什么要使用CountDownLatch?
在我们的业务中,可能会需要用到多线程去处理业务,而主线程必须乖乖等其他线程处理完后,再向用户返回处理结果,是成功还是失败。这时候我们该怎么办呢,CountDownLatch就能很好的实现我们的功能。
怎么使用CountDownLatch?
CountDownLatch的使用其实很简单,我们在主线程创建一个CountDownLatch,然后将它传递给各个子线程,主线程完成自己的业务后调用await方法挂起,各子线程完成功能后,调用countDown方法将计数器减一,CountDownLatch的计数器为0后,主线程被唤醒,处理自己的业务。
举个例子
public class CountdownlachTest {
public static void main(String[] args) {
/** 先开个玩具厂 */
ToyFactory factory = new ToyFactory();
/** 玩具厂生产玩具咯,先来50个玩具 */
int toyNum = factory.produceToy(50);
System.err.println(toyNum + "个玩具新鲜出炉");
CountDownLatch countDownLatch = new CountDownLatch(toyNum);
/** 叫销售员去卖吧 */
ToySalesperson zhangsan = new ToySalesperson("张三",12,factory,countDownLatch);
ToySalesperson lisi = new ToySalesperson("李四",12,factory,countDownLatch);
ToySalesperson wangwu = new ToySalesperson("王五",10,factory,countDownLatch);
ToySalesperson zhaoliu = new ToySalesperson("赵六",16,factory,countDownLatch);
/** 销售员干活吧 */
zhangsan.start();
lisi.start();
wangwu.start();
zhaoliu.start();
/** 继续产玩具 */
int produceToy = factory.produceToy(100);
if(produceToy <= 0) {
/** 还有玩具不给我生产,那我关厂等呗 */
try {
countDownLatch.await();
} catch (InterruptedException e) {
System.err.println("玩具厂----暂停营业呢,你们来吵我干嘛");
}
}
if(factory.toyNum <= 0) {
/** 玩具卖完了,继续开工吧 */
System.err.println("玩具厂----我又复活了,大量招工");
}
}
}
/**
* 玩具工厂
* */
class ToyFactory{
Integer toyNum = 0; // 玩具数量
/** 生产玩具 */
public int produceToy(int num) {
if(toyNum > 0) {
System.err.println("厂里还有玩具,必须先卖完,不能堆积");
return 0;
}
this.toyNum = num;
return this.toyNum;
}
}
/**
* 销售员
* */
class ToySalesperson extends Thread{
String name; // 线程名
int myToyNum; // 我的任务量
CountDownLatch countDownLatch; // 剩余总量
ToyFactory factory;
public ToySalesperson(String name,int myToyNum,ToyFactory factory,CountDownLatch countDownLatch) {
super(name);
this.name = name;
this.myToyNum = myToyNum;
this.countDownLatch = countDownLatch;
this.factory = factory;
}
@Override
public void run() {
/** 不断卖玩具 */
while(true) {
if(myToyNum <= 0) {
System.err.println(name + "----" + "我的任务完成了,玩具卖完了,老子不用再加班了!!!");
return;
}
try {
/** 模拟到处跑卖玩具 */
TimeUnit.SECONDS.sleep(2);
System.err.println(name + "----" + "终于卖出一个了,真艰难啊,还剩" + myToyNum + "个");
myToyNum--;
countDownLatch.countDown();
synchronized (factory.toyNum) {
factory.toyNum--;
}
} catch (InterruptedException e) {
/** 线程被中断 */
System.err.println(name + "----" + "老板给我穿小鞋,老子不干啦");
return;
}
}
}
}
CountDownLatch 计数器的更多相关文章
- java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用
先来讲解一下Semaphore信号灯的作用: 可以维护当前访问自身的线程个数,并提供了同步机制, 使用semaphore可以控制同时访问资源的线程个数 例如,实现一个文件允许的并发访问数. 请看下面 ...
- CycliBarriar和CountdownLatch(计数器)
CyclicBarrier可以重复使用,而CountdownLatch不能重复使用. countDownLatch这个类使一个线程等待其他线程各自执行完毕再执行. 是通过一个计数器来实现的,计数器的初 ...
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...
- JUC系列回顾之-CountDownLatch底层原理和示例
CountDownLatch 是一个同步工具类,允许一个线程或者多个线程等待其他线程完成操作,再执行. CountDownLatch(int count) 构造一个用给定计数初始化的 CountDow ...
- CountDownLatch——闭锁的实现之一
CountDownLatch实际上是一种闭锁实现.闭锁:是一种同步工具类,可以延迟线程的进度知道其到达终止状态--<Java并发编程实战>.这个怎么解释呢?简单来说,就是有1个线程需要等待 ...
- java并发之同步辅助类(Semphore、CountDownLatch、CyclicBarrier、Phaser)
线程同步辅助类,主要学习两点: 1.上述几种同步辅助类的作用以及常用的方法 2.适用场景,如果有适当的场景可以用到,那无疑是最好的 semaphore(seməˌfôr) 含义 信号量就是可以声明多把 ...
- Java中使用CountDownLatch进行多线程同步
CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantL ...
- ccse(CountDownLatch,CycliBarrier,Semaplore,Exchanger)
关于等待状态的线程调用interrupt方法报异常:InterruptedException 当线程被阻塞,比如wait,join,sleep等,在调用interrupt方法,没有占用cpu运行的线程 ...
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)
我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...
随机推荐
- 使用css实现loading的加载
使用css实现loading的加载的效果图 html代码 <div id="caseVerteClaire"> <div id="transform&q ...
- Redis 入门到分布式 (七)Redis复制的原理与优化
一.目录 Redis复制的原理与优化 什么是主从复制 全量复制和部分复制 复制的配置 故障处理 开发运维常见问题 二. 什么是主从复制 1.单机有什么问题? 单机如果机器故障,那么久无法及时提供服务: ...
- Linux (九)服务器环境搭建
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.行为守则 1.拍摄快照 Linux系统操作非常复杂,搭建开发环境时全部使用命令完成安装过程.而在Li ...
- (Java实现) 组合的输出
问题 B: [递归入门]组合的输出 时间限制: 1 Sec 内存限制: 128 MB 题目描述 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们 ...
- Java实现 LeetCode 472 连接词
472. 连接词 给定一个不含重复单词的列表,编写一个程序,返回给定单词列表中所有的连接词. 连接词的定义为:一个字符串完全是由至少两个给定数组中的单词组成的. 示例: 输入: ["cat& ...
- Java实现 LeetCode 53 最大子序和
53. 最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 ...
- 使用liunx系统自带的工具sar监控指定接口速率
1.路由器双出口部署,接口可以实现负载分担,在接口负载比例设置为1:2之后,管理员反馈流量有些异常,内网tracert -d 外网域名或者IP,都走一条链路. 2.底层尝试使用sar命令监控两个接口的 ...
- 二叉树的层次序列化和反序列化-----stringstream
string serialize(TreeNode* root) {//层序便利,将空的子节点也放入到字符串 ostringstream out; queue<TreeNode*> q; ...
- java关键字tranisent用法详解
作为java中的一个关键字,tranisent用的并不是很多,但是在某些关键场合,却又起着极为重要的作用,因此有必要对它进行一些必要的了解. 一.定义:声明不用序列化的成员域.(源自百度百科) 二.作 ...
- 常见ie9兼容问题
公司项目要求需要兼容ie9,开发过程中遇到了许多问题,在这里记录一下,希望可以帮到其他需要的小伙伴. 浏览器兼容性问题无外乎三点,css样式兼容.JavaScript兼容及h5部分标签的兼容.主要介绍 ...