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

java并发编程 juc线程类介绍

Java并发编程实战:深度解析CountDownLatch、CyclicBarrier与Semaphore

引言:线程同步的艺术

在现代多核处理器架构下,高效的并发编程能力已成为Java开发者的必备技能。java.util.concurrent包中的CountDownLatch、CyclicBarrier和Semaphore是解决线程同步问题的三把利器。本文将深入剖析这三个核心组件的实现原理、使用场景,并通过典型应用案例演示它们的实战应用技巧。


一、核心组件深度解析

1. CountDownLatch:精准控制的线程协调器

实现原理

  • 基于AQS(AbstractQueuedSynchronizer)实现共享锁模式
  • 内部维护volatile类型的计数器
  • 通过CAS操作保证原子性递减
// 典型应用场景:批量任务执行监控
public class BatchTaskMonitor {public static void main(String[] args) throws Exception {int BATCH_SIZE = 5;CountDownLatch completionSignal = new CountDownLatch(BATCH_SIZE);IntStream.range(0, BATCH_SIZE).forEach(i -> new Thread(() -> {processTask(i);completionSignal.countDown();}).start());completionSignal.await();System.out.println("所有批次任务执行完毕");}private static void processTask(int taskId) {// 模拟任务处理逻辑}
}
MainThread Thread1 Thread2 Thread3 启动 启动 启动 countDown() countDown() countDown() await()解除阻塞 MainThread Thread1 Thread2 Thread3

2. CyclicBarrier:可循环使用的线程屏障

架构设计

  • 使用ReentrantLock和Condition实现等待/通知机制
  • Generation内部类实现屏障重置
  • 支持barrierAction回调函数

突破性特性

  • 自动重置计数器(对比CountDownLatch)
  • 支持broken状态检测
  • 可选的超时等待机制
// 分阶段数据处理示例
class DataProcessingPipeline {void process() {final int WORKER_COUNT = 3;CyclicBarrier barrier = new CyclicBarrier(WORKER_COUNT, () -> System.out.println("当前阶段处理完成"));ExecutorService pool = Executors.newCachedThreadPool();for (int i = 0; i < WORKER_COUNT; i++) {pool.execute(() -> {while(hasMorePhases()) {processPhase();barrier.await(); // 等待所有工作线程完成当前阶段}});}}
}

3. Semaphore:资源访问的守门人

许可证管理机制

  • 公平/非公平两种获取模式
  • 基于AQS state字段管理许可证数量
  • 支持tryAcquire非阻塞获取

流量控制示例

class ConnectionPool {private static final int MAX_CONNECTIONS = 10;private final Semaphore available = new Semaphore(MAX_CONNECTIONS, true);public Connection getConnection() throws InterruptedException {available.acquire();return leaseConnection();}public void releaseConnection(Connection conn) {returnConnection(conn);available.release();}
}

二、组件对比与选型指南

功能维度对比矩阵

维度CountDownLatchCyclicBarrierSemaphore
重用性一次性可循环不限次数
线程关系主从协作对等协作资源竞争
核心操作countDown/awaitawaitacquire/release
典型应用场景启动准备检查分阶段任务处理连接池管理
异常处理复杂度高(涉及屏障破坏)

三、高级应用技巧

1. 复合型同步方案

// 结合Semaphore和CountDownLatch实现复杂控制
class ResourceController {private Semaphore semaphore = new Semaphore(5);private CountDownLatch initializationLatch = new CountDownLatch(1);public void initialize() {// 初始化资源initializationLatch.countDown();}public void accessResource() throws InterruptedException {initializationLatch.await();semaphore.acquire();try {// 访问受保护资源} finally {semaphore.release();}}
}

2. 超时控制策略

// 带超时的CyclicBarrier使用示例
if (barrier.await(10, TimeUnit.SECONDS) == 0) {// 最后一个到达屏障的线程执行后续操作
} else {throw new TimeoutException("等待超时");
}

四、最佳实践与陷阱规避

正确使用姿势

  1. 资源释放保证

    semaphore.acquire();
    try {// 临界区操作
    } finally {semaphore.release();
    }
    
  2. 屏障重置规范

    if (barrier.isBroken()) {barrier.reset(); // 谨慎处理屏障破坏情况
    }
    
  3. 线程池兼容性

    • 确保线程池大小 >= 屏障数(CyclicBarrier)
    • 避免线程饥饿导致的死锁

典型陷阱警示

  1. CountDownLatch误重用

    // 错误示例:
    latch.await();
    latch.countDown(); // 此时计数器已为0,操作无效
    
  2. 信号量超额释放

    semaphore.release(); // 未获取直接释放会导致许可证数量超过初始值
    
  3. 屏障死锁风险

    • 当等待线程数超过屏障数时,将导致永久阻塞

五、性能优化建议

1. 并发控制参数调优

  • 根据CPU核心数设置线程池大小
  • 使用Runtime.getRuntime().availableProcessors()获取核心数
  • 信号量数量 = 核心数 * 任务类型系数(I/O密集型建议2n+1)

2. 锁优化策略

// 使用非公平模式提升吞吐量
Semaphore highThroughputSemaphore = new Semaphore(10, false);

3. 监控与调试

  • 使用JConsole观察AQS队列状态
  • 通过ThreadMXBean检测线程阻塞情况
  • 添加JVM参数-XX:+PrintConcurrentLocks分析锁竞争

结语:选择适合的并发工具

理解这三个同步器的核心差异是构建高效并发系统的关键。CountDownLatch适用于一次性事件通知,CyclicBarrier擅长多阶段协同,而Semaphore则是资源管控的利器。掌握它们的底层实现机制,结合具体业务场景合理选用,将显著提升系统并发处理能力。

相关文章:

java并发编程 juc线程类介绍

Java并发编程实战&#xff1a;深度解析CountDownLatch、CyclicBarrier与Semaphore 引言&#xff1a;线程同步的艺术 在现代多核处理器架构下&#xff0c;高效的并发编程能力已成为Java开发者的必备技能。java.util.concurrent包中的CountDownLatch、CyclicBarrier和Semaphore…...

API接口自动化学习总结

视频&#xff1a;python 做 API接口测试 和 自动化 - 1周入门_哔哩哔哩_bilibili 资料&#xff1a;HTTP协议 - 白月黑羽 要学习接口自动化&#xff0c;先要知道http协议和requests库&#xff0c;后面则是接口手工测试和接口自动化测试。 HTTP协议&#xff1a; HTTP协议简介…...

Python中的字典:深度解析与应用实践

一、字典的本质与特性 Python字典&#xff08;Dictionary&#xff09;是以**键值对&#xff08;Key-Value Pair&#xff09;**形式存储数据的无序集合&#xff0c;使用大括号{}定义。其核心特性包括&#xff1a; 快速查找&#xff1a;基于哈希表实现&#xff0c;通过键&#…...

1. 环境准备

安装CentOS 7 配置网络 默认网络是NAT 端口转发 更改/etc/sysconfig/network-scripts/ifcfg-ens33 修改以下内容&#xff1a; BOOTPROTOstatic 启用静态IP地址 ONBOOTyes 开启自动启用网络连接 添加以下内容&#xff1a; IPADDR192.168.30.100 设置IP地址 NETMASK255.25…...

【链表】一文搞定链表算法:从基础到实战

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言例题一、两数相加二、两两交换链表中的节点三、重排链表四、合并K个升序链表五、 K个⼀组翻转链表 结语 前言 什么是链表算法&#xff1a; 链表算法&#xff0…...

瑞萨RA系列使用JLink RTT Viewer输出调试信息

引言 还在用UART调试程序么?试试JLINK的RTT Viewer吧!不需占用UART端口、低资源暂用、实时性高延时微秒级,这么好的工具还有什么理由不用了! 目录 一、JLink RTT Viewer 简介 二、软件安装 三、工程应用 3.1 SEGGER_RTT驱动包 3.2 手搓宏定义APP_PRINT 3.3 使用APP_…...

DEFI币生态重构加速,XBIT去中心化交易所引领DEX安全新范式

2025年3月18日&#xff0c;全球加密市场在监管与技术共振下迎来结构性变革。去中心化金融&#xff08;DeFi&#xff09;代币DEFI币因跨链流动性协议升级引发社区热议&#xff0c;而币应XBIT去中心化交易所&#xff08;以下简称XBIT&#xff09;凭借其链上透明验证机制、无需下载…...

高性能缓存:使用 Redis 和本地内存缓存实战示例

在现代高并发系统中&#xff0c;缓存技术是提升性能和降低数据库压力的关键手段。无论是分布式系统中的Redis缓存&#xff0c;还是本地高效的本地内存缓存&#xff0c;合理使用都能让你的应用如虎添翼。今天&#xff0c;我们将基于go-dev-frame/sponge/pkg/cache库的代码示例&a…...

Linux动态库和静态库

Linux动态库和静态库 Linux动态库和静态库动静态库的基本原理可执行程序的生成过程动静态库的本质 认识动静态库背后的库支持动静态库的命名静态链接示例 动静态库各自的特征静态库动态库 静态库的打包与使用示例文件打包1. 生成目标文件2. 打包静态库3. 组织文件使用 Makefile…...

13 IO流:字节流、字符流、缓冲流、文件复制(字节/字符/缓冲区)、字符转换流、打印流、IO框架(黑马Java视频笔记)

文章目录 IO流 >> 读写数据的方案1. 认识IO流1&#xff09;IO流的分类2&#xff09;IO流的体系 2. 文件字节输入流2.1 创建文件字节流对象2.2 读取文件1&#xff09;使用read()方法一个一个字节的读取2&#xff09;使用字节数组读取数据:byte[]3&#xff09;使用字节流读…...

深入理解 TypeScript 中的迭代器(Iterators)与生成器(Generators)

一、为什么需要迭代协议&#xff1f; 在现代 JavaScript/TypeScript 开发中&#xff0c;我们经常需要处理各种集合型数据&#xff1a;数组、Map、Set 甚至是自定义数据结构。ES6 引入的迭代协议&#xff08;Iteration Protocols&#xff09;正是为了解决统一遍历机制的问题。通…...

靶场(十四)---小白心得思路分享---Extplorer

启程&#xff1a; 开始扫描端口服务&#xff0c;发现什么都没有&#xff0c;果断进行下一步目录扫描 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 98:4e:5d:e1:e6:97:29:6f:…...

逆向中常见的加密算法识别

1、base64及换表 base64主要是将输入的每3字节&#xff08;共24bit&#xff09;按照每六比特分成一组&#xff0c;变成4个小于64的索引值&#xff0c;然后通过一个索引表得到4个可见的字符。 索引表为一个64字节的字符串&#xff0c;如果在代码中发现引用了这个索引表“ABCDEF…...

【初学者】怎样学习、使用与研究算法?

李升伟 整理 学习、使用与研究算法是一个系统化的过程&#xff0c;涉及理论学习、实践应用和深入研究。以下从学习方法、使用技巧和研究方向三个方面进行详细阐述&#xff1a; 一、学习方法 1. 分阶段学习 初级阶段&#xff1a;掌握经典算法&#xff0c;如最短路径算法&…...

【愚公系列】《高效使用DeepSeek》018-错题本整理

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

Linux上的`i2c-tools`工具集的编译构建和安装

源码复制到Ubuntu系统中并解压 的i2c-tools工具集的源码百度网盘下载链接&#xff1a; https://pan.baidu.com/s/1XNuMuT1auT1dMzYo3LAFmw?pwdi6xe 终端进入源码目录 cd /home/book/mybuild/i2c-tools-4.2执行编译构建命令 运行下面的命令进行编译构建 make CC${CROSS_COM…...

langgraph简单Demo(使用langserve实现外部调用)

前言 这个示例是研究如何使用langserve实现外部调用 接入大模型参考文章&#xff1a;接入阿里云百炼 1、安装依赖 pip install langserve fastapi uvicorn pip install sse_starlette 2、代码实现 from fastapi import FastAPI from langchain_core.messages import HumanM…...

【C#高阶编程】—单例模式详解

C# 单例模式 单例模式是一种设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。单例模式常用于需要全局唯一对象的场景&#xff0c;比如配置文件管理、日志记录、数据库连接池等。 单例模式的核心特点 私有构造函数&#xff1a;…...

折叠树报表

折叠树报表中包含了三种信息: 1.树组织信息-可展开、收拢 2.节点的统计信息(汇总求和) 3.每个节点对应的数据信息 一、准备数据 mysql8 数据库中存在两张表 org和store表。 org表和部分数据如下,其中orgname是组织的名称,codepath是完整的组织代码,seq是每个节点的顺序,可…...

Python个人学习笔记(16):模块(os)

四、os模块 主要用于文件夹处理 &#xff08;一&#xff09;文件夹相关 os.makedirs(‘dirname1/dirname2’) &#xff1a;创建文件夹目录&#xff0c;不能重复创建&#xff0c;用的多 代码&#xff1a; os.makedirs(a/b/c)结果&#xff1a; os.removedirs(‘dirname1’)&…...

虚拟地址空间(下)进程地址空间(上)

一.关于页表组成 1.权限&#xff08;rwx) 作用&#xff1a;如1.让代码区变成只读的 2.写时拷贝的实现&#xff1a;子进程创建时其页表指向的父进程代码和数据权限都是只读的&#xff0c;子进程试图修改&#xff0c;触发错误&#xff0c;系统开始写时拷贝。 来源&#xff1a;…...

【数据集分享】青藏高原两次强震玛多地震和漾濞地震的震源过程

2021年5月21日&#xff0c;5小时内在青藏高原不同区域发生了漾濞6.4级和玛多7.4级强烈地震&#xff0c;表明印度板块和欧亚大陆板块的碰撞汇聚作用下青藏高原持续和频繁的 剧烈构造运动和地震活动。本研究利用地震记录和空间对地观测同震位移资料&#xff08;InSAR&#xff09;…...

jmeter环境搭建及使用

Meter 是一个开源的性能测试工具&#xff0c;用于测试静态和动态资源的性能。 1、安装 官网下载&#xff1a; 下载地址&#xff1a;Apache JMeter - Download Apache JMeter 网盘下载&#xff1a; 通过百度网盘分享的文件&#xff1a;apache-jmeter-5.6.3.rar 链接&#x…...

Python 鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…...

网络编程--服务器双客户端聊天

写一个服务器和客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1和客户端2进行聊天&#xff0c;客户端1将聊天数据发送给服务器&#xff0c;服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 &#xff0c;客户端1使用 poll 模型实现…...

yum软件包乾坤大挪移(Yum Package Qiankun Great Migration)

yum软件包乾坤大挪移 背景 由于很多的生产环境是无法连接外网的&#xff0c;因此用yum或者dnf命令来安装软件包常常是一个比较麻烦的事情&#xff0c;原因是很多软件的依赖很复杂&#xff0c;如果要一个个下载、拷贝、再安装&#xff0c;这往往是一个非常繁琐冗杂的过程&…...

Java:读取中文,read方法

public static void main(String[] args) throws IOException {FileReader fr new FileReader("C:\\aaa\\a.txt");//字符流的底层也是一个字节一个字节读取的&#xff0c;遇到中文就一次读多个&#xff0c;GBK一次读两个&#xff0c;UTF-8一次读三个字节//idea默认U…...

[GHCTF 2025]真会布置栈吗?

题目是一个聊天室,我们先按照题目使用 /help Help: /help 显示此帮助信息 /msg [text] 在当前频道发送消息 /nick [name] 更改你的用户名 /list 列出可用的频道 /join [channel] 切换到不同的频道 /channel …...

集合的练习1-2

//练习1&#xff1a; import java.util.ArrayList;public class ArraylistTest1 {public static void main(String[] args){ArrayList<String> listnew ArrayList<>();//需求&#xff1a;定义一个集合&#xff0c;添加字符串&#xff0c;并进行遍历//遍历格式&…...

英语词性--数词

文章目录 数词概念数词分词基数词序数词 基数与序数词的区别基变序的规律 数词概念 数词&#xff08;Numerals&#xff09; 是英语中用于表示 数量&#xff08;基数&#xff09;或顺序&#xff08;序数&#xff09; 的词类&#xff0c;通常用于描述数字、计数、顺序等。 例如&…...