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

Java并发编程实战 Day 7:并发集合类详解

【Java并发编程实战 Day 7】并发集合类详解

开篇

欢迎来到"Java并发编程实战"系列的第7天!今天我们将重点探讨并发集合类(如ConcurrentHashMapCopyOnWriteArrayList),它们是Java并发编程中的核心组件之一。通过本篇文章,你将掌握这些并发集合的使用方法、实现原理以及最佳实践,为处理高并发场景提供解决方案。

注意:本文适用于有一定多线程基础的开发者,建议先复习前6天的内容以更好地理解今天的主题。


理论基础

什么是并发集合类?

并发集合类是指那些专门为多线程环境设计的集合类型,它们在保证线程安全的同时,尽可能地提升了性能。常见的并发集合类包括:

  • ConcurrentHashMap
  • CopyOnWriteArrayList
  • BlockingQueue及其子类(将在后续章节讲解)

相比传统的同步集合(如Collections.synchronizedMap()包装的集合),并发集合采用更细粒度的锁机制或无锁算法,从而减少线程间的竞争,提高并发性能。

并发集合的核心实现原理

  1. 分段锁机制:例如ConcurrentHashMap早期版本通过分段锁(Segment Lock)来实现部分区域的并发写操作,减少了锁的粒度。
  2. CAS无锁算法:从Java 8开始,ConcurrentHashMap改用基于CAS(Compare-And-Swap)的无锁算法,进一步优化了性能。
  3. 写时复制CopyOnWriteArrayList在每次修改时会创建底层数组的新副本,读操作完全无锁,适用于读多写少的场景。

适用场景

ConcurrentHashMap

  • 高频读写场景:如缓存系统中需要频繁对数据进行增删改查。
  • 统计计数器:多个线程同时更新某些计数值。

CopyOnWriteArrayList

  • 读多写少场景:如用户权限列表、配置文件管理等。
  • 事件监听器注册表:监听器通常只在初始化阶段添加或移除,运行时主要为读取。

代码实践

示例1:使用ConcurrentHashMap实现线程安全的缓存

import java.util.concurrent.ConcurrentHashMap;public class CacheExample {public static void main(String[] args) {// 创建一个线程安全的ConcurrentHashMapConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();// 模拟多个线程同时写入数据Thread writer1 = new Thread(() -> {for (int i = 0; i < 5; i++) {cache.put("Key" + i, "Value" + i);System.out.println("Writer1 added Key" + i);}});Thread writer2 = new Thread(() -> {for (int i = 5; i < 10; i++) {cache.put("Key" + i, "Value" + i);System.out.println("Writer2 added Key" + i);}});// 启动线程writer1.start();writer2.start();try {writer1.join();writer2.join();} catch (InterruptedException e) {e.printStackTrace();}// 打印最终结果System.out.println("Final Cache Content: " + cache);}
}

示例2:使用CopyOnWriteArrayList实现线程安全的事件监听器

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;public class EventListenerExample {public static void main(String[] args) {List<String> listeners = new CopyOnWriteArrayList<>();// 模拟注册监听器Thread registerThread = new Thread(() -> {for (int i = 0; i < 5; i++) {listeners.add("Listener" + i);System.out.println("Registered Listener" + i);}});// 模拟触发事件Thread triggerThread = new Thread(() -> {for (String listener : listeners) {System.out.println("Triggered " + listener);}});registerThread.start();triggerThread.start();try {registerThread.join();triggerThread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("All Listeners: " + listeners);}
}

实现原理

ConcurrentHashMap源码分析

  1. 内部结构ConcurrentHashMap由多个哈希桶组成,每个桶独立加锁。
  2. put()方法流程
    • 计算哈希值并定位到对应的桶。
    • 如果桶为空,则尝试通过CAS插入新节点。
    • 如果桶非空且未加锁,则获取锁后插入。
  3. 扩容机制:当负载因子超过阈值时,会动态扩容,扩容过程中其他线程可以协助迁移数据。

CopyOnWriteArrayList源码分析

  1. 读操作:直接返回底层数组的快照,无需加锁。
  2. 写操作:每次修改都会创建数组的新副本,确保读操作不受影响。

性能测试

我们对比了ConcurrentHashMapCollections.synchronizedMap()在高并发写入场景下的性能表现,测试代码如下:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class PerformanceTest {private static final int THREAD_COUNT = 10;private static final int OPERATIONS_PER_THREAD = 10000;public static void main(String[] args) throws InterruptedException {Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());Map<String, String> concurrentMap = new ConcurrentHashMap<>();ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);long startTime, endTime;// 测试synchronizedMapstartTime = System.nanoTime();for (int i = 0; i < THREAD_COUNT; i++) {executor.submit(() -> {for (int j = 0; j < OPERATIONS_PER_THREAD; j++) {syncMap.put("Key" + j, "Value" + j);}});}executor.shutdown();executor.awaitTermination(1, TimeUnit.MINUTES);endTime = System.nanoTime();System.out.println("SynchronizedMap Time: " + (endTime - startTime) / 1e6 + " ms");executor = Executors.newFixedThreadPool(THREAD_COUNT);// 测试ConcurrentHashMapstartTime = System.nanoTime();for (int i = 0; i < THREAD_COUNT; i++) {executor.submit(() -> {for (int j = 0; j < OPERATIONS_PER_THREAD; j++) {concurrentMap.put("Key" + j, "Value" + j);}});}executor.shutdown();executor.awaitTermination(1, TimeUnit.MINUTES);endTime = System.nanoTime();System.out.println("ConcurrentHashMap Time: " + (endTime - startTime) / 1e6 + " ms");}
}
集合类型执行时间(毫秒)
SynchronizedMap1200
ConcurrentHashMap400

可以看出,ConcurrentHashMap在高并发场景下显著优于synchronizedMap


最佳实践

  1. 选择合适的集合类型
    • 写多读少:优先考虑ConcurrentHashMap
    • 读多写少:优先考虑CopyOnWriteArrayList
  2. 避免过度使用同步:尽量减少锁的范围,提升并发性能。
  3. 合理设置初始容量:防止频繁扩容导致性能下降。

案例分析

背景

某电商平台的商品库存管理系统需要支持高并发访问,要求实时更新商品库存数量并查询剩余库存。

解决方案

使用ConcurrentHashMap存储商品ID与库存数量的映射关系,利用其高效的读写性能应对高并发需求。具体实现类似于上述示例中的缓存系统。


总结

今天我们学习了以下内容:

  1. 并发集合类的基本概念及常见实现。
  2. ConcurrentHashMapCopyOnWriteArrayList的使用方法与底层原理。
  3. 如何通过性能测试验证并发集合的优势。

明天我们将进入进阶篇的第一天——Java内存模型深度解析,敬请期待!

参考资料

  1. Oracle官方文档 - ConcurrentHashMap
  2. Java并发编程的艺术
  3. Java内存模型与并发编程

核心技能总结

通过本文的学习,你掌握了以下核心技能:

  • 使用ConcurrentHashMapCopyOnWriteArrayList解决线程安全问题。
  • 分析并发集合类的底层实现原理。
  • 在实际工作中根据业务场景选择合适的并发集合。

这些技能可以直接应用于构建高性能、高可用的并发系统中,例如缓存系统、权限管理模块等。

http://www.xdnf.cn/news/12022.html

相关文章:

  • Docker轻松搭建Neo4j+APOC环境
  • 《PyTorch Hub:解锁深度学习模型的百宝箱》
  • 物流数据接口新玩法:跨境订单处理效率提升200%
  • echarts显示/隐藏标签的同时,始终显示饼图中间文字
  • 简数采集技巧之快速获取特殊链接网址URL方法
  • Playwright 测试框架 - Python
  • 软件工程专业的本科生应该具备哪些技能
  • 【Bluedroid】蓝牙启动之gatt_init 流程源码解析
  • DrissionPage爬虫包实战分享
  • 汽车加气站操作工证考试重点
  • 文献阅读|基于PSMA PET/CT与mpMRI多模态深度学习预测前列腺癌的不良病变
  • Spring AI 之工具调用
  • cpp多线程学习
  • 无人机光纤FC接口模块技术分析
  • [华为eNSP] 在eNSP上实现IPv4地址以及IPv4静态路由的配置
  • 融智学的数学基础,通过微分几何的纤维丛结构,构建理论框架模型包含生物层、动物层、心智层、人造物层和人格层五个维度
  • C++算法训练营 Day7 哈希表及双指针
  • 聊聊FlaUI:让Windows UI自动化测试优雅起飞!
  • Deepin 安装 Nginx
  • (eNSP)配置WDS手拉手业务
  • .NET 生态中的 MCP 项目及技术分析
  • 那些Java 线程中断的实现方式
  • 单锁与分布式锁
  • AI工程师的武器库:核心技术与实战案例
  • MCP与检索增强生成(RAG):AI应用的强大组合
  • 《Coevolutionary computation and its application》协同演化及其应用中文对照·第一章
  • 告别无效号码,精准营销从空号过滤开始
  • 固定ip和非固定ip的区别是什么?如何固定ip地址
  • Lifecycle 核心原理面试回答
  • DeepSwiftSeek 开源软件 |用于 DeepSeek LLM 模型的 Swift 客户端 |轻量级和高效的 DeepSeek 核心功能通信