CountDownLatch的理解和使用 多线程同步器

CountDownLatch的理解和使用

在笔者想要了解Thrift时候,找到一个博主写的系统间通信技术的架构设计,在了解和学习的过程中遇到很多小问题和基础知识,自己还是不够清楚,就查询和总结下。

因为笔者也都是从网上找的一些资料,好的资料笔者都是自己收敲一遍,这样觉得能够加深下印象,引发更多的思考,毕竟很多时候笔者感觉自己都是七秒的记忆。

在第一篇文章中遇到了一个CountDownLatch同步计数器,当计数器数值减为0时,所有受其影响而等待的线程将会被激活,这样保证模拟并发请求的真实性。

CountDownLatch概念

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。

CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

CountDownLatch的用法

CountDownLatch典型用法:1、某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为new CountDownLatch(n),每当一个任务线程执行完毕,就将计数器减1 countdownLatch.countDown(),当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。

CountDownLatch典型用法:2、实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的CountDownLatch(1),将其计算器初始化为1,多个线程在开始执行任务前首先countdownlatch.await(),当主线程调用countDown()时,计数器变为0,多个线程同时被唤醒。

CountDownLatch的不足

CountDownLatch是一次性的,计算器的值只能在构造方法中初始化一次,之后没有任何机制再次对其设置值,当CountDownLatch使用完毕后,它不能再次被使用。

 

CountDownLatch(倒计时计算器)使用说明

方法说明

public void countDown()

  递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.

public boolean await(long timeout,TimeUnit unit) throws InterruptedException

  使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。如果当前计数为零,则此方法立刻返回true值。

  如果当前计数大于零,则出于线程调度目的,将禁用当前线程,且在发生以下三种情况之一前,该线程将一直出于休眠状态:

  由于调用countDown()方法,计数到达零;或者其他某个线程中断当前线程;或者已超出指定的等待时间。

  • 如果计数到达零,则该方法返回true值。
  • 如果当前线程,在进入此方法时已经设置了该线程的中断状态;或者在等待时被中断,则抛出InterruptedException,并且清除当前线程的已中断状态。
  • 如果超出了指定的等待时间,则返回值为false。如果该时间小于等于零,则该方法根本不会等待。

参数:

  timeout-要等待的最长时间

  unit-timeout 参数的时间单位

返回:

  如果计数到达零,则返回true;如果在计数到达零之前超过了等待时间,则返回false

抛出:

  InterruptedException-如果当前线程在等待时被中断

例子1:

  主线程等待子线程执行完成在执行

 

package com.example.demo.CountDownLatchDemo;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 主线程等待子线程执行完成再执行*/
public class CountdownLatchTest1 {public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(3);final CountDownLatch latch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");Thread.sleep((long) (Math.random() * 10000));System.out.println("子线程"+Thread.currentThread().getName()+"执行完成");latch.countDown();//当前线程调用此方法,则计数减一} catch (InterruptedException e) {e.printStackTrace();}}};service.execute(runnable);}try {System.out.println("主线程"+Thread.currentThread().getName()+"等待子线程执行完成...");latch.await();//阻塞当前线程,直到计数器的值为0System.out.println("主线程"+Thread.currentThread().getName()+"开始执行...");} catch (InterruptedException e) {e.printStackTrace();}}
}

 

例子2:

  百米赛跑,4名运动员选手到达场地等待裁判口令,裁判一声口令,选手听到后同时起跑,当所有选手到达终点,裁判进行汇总排名

 

package com.example.demo.CountDownLatchDemo;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CountdownLatchTest2 {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1);final CountDownLatch cdAnswer = new CountDownLatch(4);for (int i = 0; i < 4; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {System.out.println("选手" + Thread.currentThread().getName() + "正在等待裁判发布口令");cdOrder.await();System.out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");Thread.sleep((long) (Math.random() * 10000));System.out.println("选手" + Thread.currentThread().getName() + "到达终点");cdAnswer.countDown();} catch (InterruptedException e) {e.printStackTrace();}}};service.execute(runnable);}try {Thread.sleep((long) (Math.random() * 10000));System.out.println("裁判"+Thread.currentThread().getName()+"即将发布口令");cdOrder.countDown();System.out.println("裁判"+Thread.currentThread().getName()+"已发送口令,正在等待所有选手到达终点");cdAnswer.await();System.out.println("所有选手都到达终点");System.out.println("裁判"+Thread.currentThread().getName()+"汇总成绩排名");} catch (InterruptedException e) {e.printStackTrace();}service.shutdown();}
}

 

 原文链接: https://blog.csdn.net/joenqc/article/details/76794356

       https://www.cnblogs.com/tstd/p/4987935.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库操作DDL

show database; 查看所有数据库 drop database db_name; 删除数据库 create database db_name;创建数据库 一个数据库对应一个文件夹 create database if not exists db_name; show warnings; 查看所有警告 show create databae db_name;查看创建的数据库 create database if n…

细数Android开发者的艰辛历程,已拿offer附真题解析

笼统来说&#xff0c;中年程序员容易被淘汰的原因其实不外乎三点。 1、输出能力已到顶点。这个人奋斗十来年了&#xff0c;依旧碌碌无为&#xff0c;很明显这人的天花板就这样了&#xff0c;说白了&#xff0c;天赋就这样。 2、适应能力越来越差。年纪大&#xff0c;有家庭&…

原子操作类AtomicInteger详解

为什么需要AtomicInteger原子操作类&#xff1f; 对于Java中的运算操作&#xff0c;例如自增或自减&#xff0c;若没有进行额外的同步操作&#xff0c;在多线程环境下就是线程不安全的。num解析为numnum1&#xff0c;明显&#xff0c;这个操作不具备原子性&#xff0c;多线程并…

移动端Rem之讲解总结

日妈常说的H5页面&#xff0c;为啥叫H5页面嘛&#xff0c;不就是手机上展示的页面吗&#xff1f;那是因为啊手机兼容所有html5新特性&#xff0c;所以跑在手机上的页面也叫h5页面&#xff0c;跨平台&#xff08;安装ios),基于webview&#xff0c;它就是终端开发的一个组件&…

终于有人把安卓程序员必学知识点全整理出来了,送大厂面经一份!

除了Bug&#xff0c;最让你头疼的问题是什么&#xff1f;单身&#xff1f;秃头&#xff1f;996?面试造火箭&#xff0c;工作拧螺丝&#xff1f; 作为安卓开发者&#xff0c;除了Bug&#xff0c;经常会碰到下面这些问题&#xff1a; 应用卡顿&#xff0c;丢帧&#xff0c;屏幕画…

ABA问题

CAS&#xff1a;对于内存中的某一个值V&#xff0c;提供一个旧值A和一个新值B。如果提供的旧值V和A相等就把B写入V。这个过程是原子性的。 CAS执行结果要么成功要么失败&#xff0c;对于失败的情形下一班采用不断重试。或者放弃。 ABA&#xff1a;如果另一个线程修改V值假设原…

mq引入以后的缺点

系统可用性降低? 一旦mq不能使用以后,系统A不能发送消息到mq,系统BCD无法从mq中获取到消息.整个系统就崩溃了. 如何解决: 系统复杂程度增加? 加入mq以后,mq引入来的问题很多,然后导致系统的复杂程度增加. 如何解决 系统的一致性降低? 有人给系统A发送了一个请求,本来这个请求…

网易云的朋友给我这份339页的Android面经,成功入职阿里

IT行业的前景 近几年来&#xff0c;大数据、人工智能AI、物联网等一些技术不断发展&#xff0c;也让人们看到了IT行业的繁荣与良好的前景。越来越多的高校学府加大了对计算机的投入&#xff0c;设立相应的热门专业来吸引招生。当然也有越来越多的人选择从事这个行业&#xff0…

AQS相关逻辑解析

关心QPS TPS 如何让线程停留在lock 1、竞争锁-(拿到锁的线程、没拿到锁的线程) 临界区的资源&#xff08;static redis 数据库变量 配置中心config zookeeper&#xff09;大家共享都可以获得的资源 临界区没拿到锁的未拿到锁线程进行停留 2、怎么让线程停留在Lock方法里 …

git介绍和常用操作

转载于:https://www.cnblogs.com/kesz/p/11124423.html

网易云的朋友给我这份339页的Android面经,满满干货指导

想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样~。 25%的面试官会在头5分钟内决定面试的结果60%的面试官会在头15分钟内决定面试的结果 一般来说&#xff0c;一场单面的时间在30分钟左右&…

synchronized 和Lock区别

synchronized实现原理 Java中每一个对象都可以作为锁&#xff0c;这是synchronized实现同步的基础&#xff1a; 普通同步方法&#xff0c;锁是当前实例对象静态同步方法&#xff0c;锁是当前类的class对象同步方法块&#xff0c;锁是括号里面的对象 当一个线程访问同步代码块…

美团安卓面试,难道Android真的凉了?快来收藏!

我所接触的Android开发者&#xff0c;百分之九十五以上 都遇到了以下几点致命弱点&#xff01; 如果这些问题也是阻止你升职加薪&#xff0c;跳槽大厂的阻碍。 那么我确信可以帮你突破瓶颈&#xff01; 1.开发者的门越来越高&#xff1a; 小厂的机会少了&#xff0c;大厂…

django -- 实现ORM登录

前戏 上篇文章写了一个简单的登录页面&#xff0c;那我们可不可以实现一个简单的登录功能呢&#xff1f;如果登录成功&#xff0c;给返回一个页面&#xff0c;失败给出错误的提示呢&#xff1f; 在之前学HTML的时候&#xff0c;我们知道&#xff0c;网页在往服务器提交数据的时…

美团点评APP在移动网络性能优化的实践,通用流行框架大全

" 对于程序员来说&#xff0c;如果哪一天开始他停止了学习&#xff0c;那么他的职业生涯便开始宣告消亡。” 高薪的IT行业是众多年轻人的职业梦想&#xff0c;然而&#xff0c;一旦身入其中却发觉没有想像中那么美好。被称为IT蓝领的编程员&#xff0c;工作强度大&#xf…

java 8大happen-before原则超全面详解

再来重复下八大原则&#xff1a; 单线程happen-before原则&#xff1a;在同一个线程中&#xff0c;书写在前面的操作happen-before后面的操作。锁的happen-before原则&#xff1a;同一个锁的unlock操作happen-before此锁的lock操作。volatile的happen-before原则&#xff1a;对…

centos7.0利用yum快速安装mysql8.0

我这里直接使用MySQL Yum存储库的方式快速安装&#xff1a; 抽象 MySQL Yum存储库提供用于在Linux平台上安装MySQL服务器&#xff0c;客户端和其他组件的RPM包。这些软件包还可以升级和替换从Linux发行版本机软件存储库安装的任何第三方MySQL软件包&#xff0c;如果可以从MySQL…

腾讯3轮面试都问了Android事件分发,论程序员成长的正确姿势

前言 这些题目是网友去美团等一线互联网公司面试被问到的题目。笔者从自身面试经历、各大网络社交技术平台搜集整理而成&#xff0c;熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。 主要分为以下几部分&#xff1a; &#xff08;1&#xff09;Android面试题 …

happens-before规则和as-if-serial语义

概述 本文大部分整理自《Java并发编程的艺术》&#xff0c;温故而知新&#xff0c;加深对基础的理解程度。 指令序列的重排序 我们在编写代码的时候&#xff0c;通常自上而下编写&#xff0c;那么希望执行的顺序&#xff0c;理论上也是逐步串行执行&#xff0c;但是为了提高…

安装nodejs

1.安装nodejs&#xff1a;node-v8.12.0-x64.msi; 2.检测是否安装成功&#xff1a; 3.地址栏打开命令行:输入 cmd回车 4.检测node是否安装成功&#xff1a;node -v 看到版本号就是安装成功了 5.检测npm是否成功:npm -v 是安装成功了 6、如果npm成功了&#xff0c;把 package.js…