当前位置: 首页 > news >正文

CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结

文章目录

  • CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结
    • 一、CountDownLatch
    • 二、CyclicBarrier
    • 三、Semaphore
    • 总结

CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结

在Java多线程编程中,有三种常见的同步工具类:CountDownLatch、CyclicBarrier、Semaphore。这些工具类使得我们可以在多个线程之间进行协调,实现更高效的并发处理。本文将对它们的原理和实例进行分析总结。

一、CountDownLatch

CountDownLatch是一个计数器类,用来控制线程等待其他线程执行完毕再继续执行。这个类通常用于主线程等待多个子线程完成任务后再进行下一步操作。CountDownLatch的实现基于AQS(AbstractQueuedSynchronizer),使用了共享锁的方式。

CountDownLatch的使用思路比较简单,首先创建一个CountDownLatch对象,并把需要等待的线程数量传入CountDownLatch的构造方法。然后在每个子线程完成任务时通过countDown()方法来减少计数器的值。当计数器变为0时,await()方法会返回,主线程就可以继续执行下一步操作。

下面是一个简单的示例代码:

public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {int threadCount = 5;CountDownLatch countDownLatch = new CountDownLatch(threadCount);for (int i = 0; i < threadCount ; i++) {new Thread(() -> {try {Thread.sleep(1000L);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 执行完毕");countDownLatch.countDown();}).start();}countDownLatch.await();System.out.println("所有线程执行完毕");}
}

以上代码中,我们创建了一个CountDownLatch对象,并传入需要等待的线程数量。然后通过for循环创建了5个子线程,每个子线程都会睡眠1秒钟,模拟执行任务。当每个子线程完成任务后,调用countDown()方法来减少计数器的值。最后在主线程中调用await()方法来等待所有子线程完成任务。

二、CyclicBarrier

CyclicBarrier也是一个很有用的同步工具类,它可以让一组线程到达某个屏障(也可以理解为关卡)时被阻塞,直到所有线程都到达该屏障时才能继续执行。CyclicBarrier和CountDownLatch的区别在于,CountDownLatch只能使用一次,而CyclicBarrier可以重复使用。

CyclicBarrier的实现也是基于AQS(AbstractQueuedSynchronizer),但是使用了独占锁的方式。CyclicBarrier的使用思路也比较简单,首先创建一个CyclicBarrier对象,并把需要等待的线程数量和到达该屏障时需要执行的动作(可选)传入CyclicBarrier的构造方法。当所有线程到达该屏障时,CyclicBarrier会自动调用之前设置的动作(如果有),然后所有线程就可以继续执行接下来的操作。

下面是一个简单的示例代码:

public class CyclicBarrierDemo {public static void main(String[] args) throws InterruptedException, BrokenBarrierException {int threadCount = 3;CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount, () -> System.out.println("所有线程到达屏障"));for (int i = 0; i < threadCount ; i++) {new Thread(() -> {try {Thread.sleep(1000L);System.out.println(Thread.currentThread().getName() + " 到达屏障");cyclicBarrier.await();System.out.println(Thread.currentThread().getName() + " 继续执行");} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}).start();}}
}

以上代码中,我们创建了一个CyclicBarrier对象,并传入需要等待的线程数量和到达屏障时需要执行的动作。然后通过for循环创建了3个子线程,每个子线程都会睡眠1秒钟,并在到达屏障时调用await()方法。当所有子线程都到达屏障时,CyclicBarrier会自动执行之前设置的动作(输出“所有线程到达屏障”),然后所有线程就可以继续执行接下来的操作。

三、Semaphore

Semaphore是另一种常见的同步工具类,它可以限制同时访问某个共享资源的线程数量。Semaphore的实现也是基于AQS(AbstractQueuedSynchronizer),使用了共享锁的方式。

Semaphore的使用思路比较简单,首先创建一个Semaphore对象,并把该共享资源的数量传入Semaphore的构造方法。然后在每个需要访问该共享资源的线程中调用acquire()方法来获取访问权限,在使用完共享资源后再调用release()方法来释放访问权限。

下面是一个简单的示例代码:

public class SemaphoreDemo {public static void main(String[] args) {int threadCount = 10;Semaphore semaphore = new Semaphore(2);for (int i = 0; i < threadCount ; i++) {new Thread(() -> {try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + " 获取访问权限");Thread.sleep(1000L);} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();System.out.println(Thread.currentThread().getName() + " 释放访问权限");}}).start();}}
}

以上代码中,我们创建了一个Semaphore对象,并传入该共享资源的数量。然后通过for循环创建了10个子线程,每个子线程需要获取访问权限才能执行,如果访问权限已满则需要等待其他线程释放访问权限。当使用完共享资源后,子线程需要调用release()方法来释放访问权限。

总结

本文分析了CountDownLatch、CyclicBarrier、Semaphore三种常见的同步工具类的原理和实例。这些工具类可以帮助我们在多个线程之间进行协调,实现更高效的并发编程。在使用这些工具类时,需要注意不同工具类的区别和使用场景,以及合理地控制线程的数量和访问权限,避免出现死锁等问题。

相关文章:

CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结

文章目录 CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结一、CountDownLatch二、CyclicBarrier三、Semaphore总结 CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结 在Java多线程编程中&#xff0c;有三种常见的同步工具类&#xff1a;CountDownL…...

企业电子招投标系统源码之了解电子招标投标全流程

随着各级政府部门的大力推进&#xff0c;以及国内互联网的建设&#xff0c;电子招投标已经逐渐成为国内主流的招标投标方式&#xff0c;但是依然有很多人对电子招投标的流程不够了解&#xff0c;在具体操作上存在困难。虽然各个交易平台的招标投标在线操作会略有不同&#xff0…...

SpringCloud之Gateway组件简介

网关的理解 网关类似于海关或者大门&#xff0c;出入都需要经过这个网关。别人不经过这个网关&#xff0c;永远也看不到里面的东西。可以在网关进行条件过滤&#xff0c;比如大门只有对应的钥匙才能入内。网关和大门一样&#xff0c;永远暴露在最外面 不使用网关 前端需要记住每…...

GoNote第三章 主流框架加对比

GoNote第三章 主流框架加对比 Golang主流框架介绍 自从面市以来&#xff0c;Golang成为了程序员在编写API和开发Web服务时的首选之一。近90%的受访者表示会在自己下一组项目中持续使用Golang。与我们熟悉的C和C类似&#xff0c;Go语言也是现有Golang的“灵魂”。而Golang则是…...

Quartz框架详解分析

文章目录 1 Quartz框架1.1 入门demo1.2 Job 讲解1.2.1 Job简介1.2.2 Job 并发1.2.3 Job 异常1.2.4 Job 中断 1.3 Trigger 触发器1.3.1 SimpleTrigger1.3.2 CornTrigger 1.4 Listener监听器1.5 Jdbc store1.5.1 简介1.5.2 添加pom依赖1.5.3 建表SQL1.5.4 配置文件quartz.propert…...

Nginx专题-基于多网卡的主机配置

文章目录 Nginx 基于多网卡的主机实现一、虚拟机前置环境准备ifcfg-ens32配置文件的内容参考ifcfg-ens33配置文件的内容 二、案例演示修改nginx.conf配置文件解决中文乱码 Nginx 基于多网卡的主机实现 一、虚拟机前置环境准备 点击虚拟机右下角的 红色标框按钮&#xff0c;然后…...

4.2和4.3、MAC地址、IP地址、端口

计算机网络等相关知识可以去小林coding进行巩固&#xff08;点击前往&#xff09; 4.2和4.3、MAC地址、IP地址、端口 1.MAC地址的简介2.IP地址①IP地址简介②IP地址编址方式③A类IP地址④B类IP地址⑤C类IP地址⑥D类IP地址⑧子网掩码 3.端口①简介②端口类型 1.MAC地址的简介 …...

放弃 console.log 吧!用 Debugger 你能读懂各种源码

很多同学不知道为什么要用 debugger 来调试&#xff0c;console.log 不行么&#xff1f; 还有&#xff0c;会用 debugger 了&#xff0c;还是有很多代码看不懂&#xff0c;如何调试复杂源码呢&#xff1f; 这篇文章就来讲一下为什么要用这些调试工具&#xff1a; console.lo…...

epoll机制解析

一、epoll实现原理 1、实现原理 epoll通过3个方法来实现对句柄的监控操作&#xff0c;要深刻理解epoll&#xff0c;首先得了解epoll的三大关键要素&#xff1a;mmap、红黑树、链表。下面是epoll的框架图&#xff0c;如下&#xff1a; mmap epoll是通过内核与用户空间mmap同一块…...

基于 SpringBoot + Vue 实现的可视化拖拽编辑的大屏项目

今天给小伙伴们分享一个基于 SpringBoot Vue 实现的可视化拖拽编辑的大屏项目&#xff1b; 一、简介 这个是一个开源的一个BI平台&#xff0c;酷炫大屏展示&#xff0c;能随时随地掌控业务动态&#xff0c;让每个决策都有数据支撑。 多数据源支持&#xff0c;内置mysql、el…...

我们为什么要写作?

为什么要写书是一个很难回答的问题&#xff0c;因为从不同的角度&#xff0c;会有不同的答案。 最近ChatGPT很火&#xff01;诸事不决&#xff0c;先问问ChatGPT&#xff0c;看看它是怎么回答的。 ChatGPT给出的答案还是比较全&#xff0c;虽然没有“一本正经的胡说八道”&…...

设计模式:创建者模式 - 建造者模式

文章目录 1.概述2.结构3.实例4.优缺点5.使用场景6.模式扩展 1.概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某…...

String a = new String(“abc“); 创建了几个对象?String a = “abc“; 呢?

String a new String(“abc”); 创建了几个对象&#xff1f;String a “abc”; 呢&#xff1f; 答案&#xff1a;String a new String(“abc”); 创建了1个或2个对象&#xff1b;String a “abc”; 创建了0个或1个都对象 String a new String(“abc”); 创建过程 首先在…...

keepalived+nginx安装

欢迎使用ShowDoc&#xff01; 1、安装基础包&#xff1a; yum -y install libnl libnl-devel 2、上传包&#xff1a; tar -zxvf keepalived-2.0.20.tar.gz -C /data/imas/base_soft mkdir -p /data/imas/base_soft/keepalived cd /data/imas/base_soft/keepalived-2.0.20 .…...

硬盘格式化工具,强烈推荐这个!

案例&#xff1a;硬盘格式化工具推荐 【我的电脑已经用了好几年了&#xff0c;硬盘存储容量严重不够了&#xff0c;最近想把它格式化&#xff0c;但却不知道怎么操作&#xff0c;大家有什么比较好的硬盘格式化工具可以推荐吗&#xff1f;】 硬盘作为存储设备&#xff0c;我们…...

Python的异常捕获和处理

程序在运行过程当中&#xff0c;不可避免的会出现一些错误&#xff0c;比如&#xff1a;使用了没有赋值过的变量&#xff0c;使用了不存在的索引&#xff0c;一个数字除以0 …… 这些错误在程序中&#xff0c;我们称其为异常。 程序运行过程中&#xff0c;一旦出现异常将会导致…...

oracle学习之rownum和rowid

rownum先百度一波https://www.cnblogs.com/xfeiyun/p/16355165.html rownum是oracle特有的一个关键字。 对于基表&#xff0c;在insert记录时&#xff0c;oracle就按照insert的顺序&#xff0c;将rownum分配给每一行记录&#xff0c;因此在select一个基表的时候&#xff0c;r…...

为什么说过早优化是万恶之源?

Donald Knuth&#xff08;高德纳&#xff09;是一位计算机科学界的著名学者和计算机程序设计的先驱之一。他被誉为计算机科学的“圣经”《计算机程序设计艺术》的作者&#xff0c;提出了著名的“大O符号”来描述算法的时间复杂度和空间复杂度&#xff0c;开发了TeX系统用于排版…...

如何用 ModelScope 实现 “AI 换脸” 视频

前言 当下&#xff0c;视频内容火爆&#xff0c;带有争议性或反差大的换脸视频总能吸引人视线。虽然 AI 换脸在市面上已经流行了许久&#xff0c;相关制作工具或移动应用也是数不胜数。但是多数制作工具多数情况下不是会员就是收费&#xff0c;而且替换模板有限。以下在实战的角…...

怎么样成为一名Python工程师?到底要会哪些东西?你会了多少?

目录 重点&#xff1a;爬虫部分项目、源码展示python数据分析可视化大屏看板python爬虫爬取淘宝卤鸭货商品数据python游戏开发python自动化办公 重点&#xff1a; 1、做一名程序员&#xff0c;绝对要耐得住寂寞&#xff0c;并且要一直有点兴趣促进你学习。如果你完全没兴趣&am…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...