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的演示案例.这里再系统总结 ...
随机推荐
- 学习使用re做解析器爬小说
一.背景:近期学习python爬虫中看到,在对网页内容进行解析的技术中,re正则表达式工具也是一个很好的工具,使用re编制爬虫工具正好熟悉re正则表达式的使用. 二.环境及爬取目标 1.linux c ...
- 快速搭建基于Spring Boot + Spring Security 环境
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.Spring Security 权限管理框架介绍 简介: Spring Security 提供了基于 ...
- Java实现 LeetCode 357 计算各个位数不同的数字个数
357. 计算各个位数不同的数字个数 给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n . 示例: 输入: 2 输出: 91 解释: 答案应为除去 11, ...
- Java实现 LeetCode 344 反转字符串
344. 反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间 ...
- java实现第九届蓝桥杯最大乘积
最大乘积 把 1~9 这9个数字分成两组,中间插入乘号, 有的时候,它们的乘积也只包含1~9这9个数字,而且每个数字只出现1次. 比如: 984672 * 351 = 345619872 98751 ...
- 小师妹学JavaIO之:目录还是文件
目录 简介 linux中的文件和目录 目录的基本操作 目录的进阶操作 目录的腰疼操作 总结 简介 目录和文件傻傻分不清楚,目录和文件的本质到底是什么?在java中怎么操纵目录,怎么遍历目录.本文F师兄 ...
- Pipeline 脚本调用 mvn 命令失败
问题描述 jenkins构建job时 提示mvn 未找到命令 + export JAVA_HOME=/home/tools/jdk1.8.0_221 + JAVA_HOME=/home/tools/j ...
- 创建sudo -i免密权限账户
项目原因,服务器需要创建普通用户,但又不能让用户拿到root密码. 创建用户 [root@bogon ~]# groupadd connect [root@bogon ~]# useradd -g c ...
- 注解实现SpringCache自定义失效时间
注解实现SpringCache自定义失效时间 SpringCache是一个很方便的缓存框架,但是官方提供的缓存的配置只有全局的缓存失效时间,没有针对某个命名空间做配置,因为工作上业务的关系需要针对某一 ...
- 2020/06/06 JavaScript高级程序设计 面向对象的程序设计
ECMAScript虽然是一种面向对象的语言,但是他没有类的概念.所以他的对象也与其他语言中的对象有所不同. ECMA-262定义对象:一组没有特定顺序的值. 6.1 理解对象 创建对象的方法: 1. ...