Java并发编程利器:从ConcurrentHashMap到Fork/Join的奇幻之旅

news/2025/10/29 17:13:36/文章来源:https://www.cnblogs.com/sun-10387834/p/19171977

上篇讲了Lock锁、AQS相关的内容,本篇讲一下线程安全的类,拿来即用无需其他操作就能达到线程安全的效果,省力又省心 ~ ~

你是否曾为多线程编程中的各种坑而头疼?本文将用生动比喻和实用代码,带你轻松掌握Java并发容器的精髓,让你的多线程程序既安全又高效!

引言:为什么我们需要并发容器?

想象一下传统的超市结账场景:只有一个收银台,所有人排成一队,效率低下。这就是传统集合在多线程环境下的写照。

而现代并发容器就像拥有多个收银台的智能超市

  • 多个收银台同时工作
  • 智能分配顾客到不同队列
  • 收银员之间互相协助

在Java并发世界中,我们有三大法宝:

  1. ConcurrentHashMap - 智能分区的储物柜系统
  2. ConcurrentLinkedQueue - 无锁的快速通道
  3. 阻塞队列 - 有协调员的等待区
  4. Fork/Join框架 - 团队协作的工作模式

让我们一一探索它们的魔力!

1. ConcurrentHashMap:智能分区的储物柜系统

1.1 传统Map的问题:独木桥的困境

// 传统HashMap在多线程环境下就像独木桥
public class HashMapProblem {public static void main(String[] args) {Map<String, String> map = new HashMap<>();// 多个线程同时操作HashMap,就像多人同时过独木桥// 结果:有人掉水里(数据丢失),桥塌了(死循环)}
}

1.2 ConcurrentHashMap的解决方案:多车道高速公路

分段锁设计:把整个Map分成多个小区域,每个区域独立加锁

ConcurrentHashMap架构:├── 区域1 (锁1) → 储物柜组1├── 区域2 (锁2) → 储物柜组2├── 区域3 (锁3) → 储物柜组3└── ...

核心优势

  • 写操作只锁住对应的区域,其他区域仍可读写
  • 读操作基本不需要加锁
  • 大大提高了并发性能

1.3 实战示例:高性能缓存系统

/*** 基于ConcurrentHashMap的高性能缓存* 像智能储物柜系统,支持高并发存取*/
public class HighPerformanceCache<K, V> {private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();// 获取或计算缓存值(线程安全且高效)public V getOrCompute(K key, Supplier<V> supplier) {return cache.computeIfAbsent(key, k -> new CacheEntry<>(supplier.get())).getValue();}// 批量获取,利用并发特性public Map<K, V> getAll(Set<K> keys) {Map<K, V> result = new HashMap<>();keys.forEach(key -> {CacheEntry<V> entry = cache.get(key);if (entry != null && !entry.isExpired()) {result.put(key, entry.getValue());}});return result;}
}

2. ConcurrentLinkedQueue:无锁的快速通道

2.1 无锁队列的魔法

传统队列就像只有一个入口的隧道,所有车辆必须排队。而ConcurrentLinkedQueue就像多入口的立体交通枢纽

// 无锁队列的生动理解
public class LockFreeQueueAnalogy {public void trafficHubComparison() {// 传统阻塞队列:单入口隧道,经常堵车// ConcurrentLinkedQueue:立体交通枢纽,多入口同时通行// 秘密武器:CAS(Compare-And-Swap)算法}
}

2.2 CAS:优雅的竞争解决

CAS就像礼貌的询问:

public class PoliteInquiry {public void casAnalogy() {// 传统加锁:像抢座位,谁先坐到就是谁的// CAS无锁:像礼貌询问"这个座位有人吗?"// 如果没人就坐下,有人就找下一个座位}
}

2.3 实战示例:高并发任务处理器

/*** 基于ConcurrentLinkedQueue的高性能任务处理器* 像高效的快递分拣中心*/
public class HighPerformanceTaskProcessor {private final ConcurrentLinkedQueue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();// 提交任务 - 无锁操作,极高吞吐量public void submit(Runnable task) {taskQueue.offer(task);  // 像快递放入分拣流水线startWorkerIfNeeded();}// 工作线程 - 无锁获取任务private class Worker implements Runnable {public void run() {while (!Thread.currentThread().isInterrupted()) {Runnable task = taskQueue.poll();  // 像从流水线取快递if (task != null) {task.run();  // 处理任务}}}}
}

3. 阻塞队列:有协调员的等待区

3.1 阻塞队列的四种行为模式

想象餐厅的四种接待方式:

public class RestaurantReception {public void fourBehaviors() {// 1. 抛出异常 - 霸道的服务员//    "没位置了!走开!"// 2. 返回特殊值 - 礼貌的前台  //    "抱歉现在没位置,您要不等会儿?"// 3. 一直阻塞 - 耐心的门童//    "请您在这稍等,有位置我马上叫您"// 4. 超时退出 - 体贴的经理//    "请您等待10分钟,如果还没位置我帮您安排其他餐厅"}
}

3.2 七种阻塞队列:不同的餐厅风格

Java提供了7种阻塞队列,每种都有独特的"经营理念":

ArrayBlockingQueue:传统固定座位餐厅

// 有10个桌位的餐厅,公平模式
ArrayBlockingQueue<String> restaurant = new ArrayBlockingQueue<>(10, true);

LinkedBlockingQueue:可扩展的连锁餐厅

// 最大容纳1000人的餐厅
LinkedBlockingQueue<Order> orderQueue = new LinkedBlockingQueue<>(1000);

PriorityBlockingQueue:VIP贵宾厅

// 按客户等级服务的贵宾厅
PriorityBlockingQueue<Customer> vipLounge = new PriorityBlockingQueue<>();

DelayQueue:延时电影院

// 电影到点才能入场
DelayQueue<MovieScreening> schedule = new DelayQueue<>();

SynchronousQueue:一对一传球游戏

// 不存储元素,每个put必须等待一个take
SynchronousQueue<String> ballChannel = new SynchronousQueue<>(true);

3.3 实战示例:生产者-消费者模式

/*** 生产者-消费者模式的完美实现* 像工厂的装配流水线*/
public class ProducerConsumerPattern {private final BlockingQueue<Item> assemblyLine;public ProducerConsumerPattern(int lineCapacity) {this.assemblyLine = new ArrayBlockingQueue<>(lineCapacity);}// 生产者:原材料入库public void startProducers(int count) {for (int i = 0; i < count; i++) {new Thread(() -> {while (true) {Item item = produceItem();assemblyLine.put(item);  // 流水线满时等待}}).start();}}// 消费者:产品出库public void startConsumers(int count) {for (int i = 0; i < count; i++) {new Thread(() -> {while (true) {Item item = assemblyLine.take();  // 流水线空时等待consumeItem(item);}}).start();}}
}

4. Fork/Join框架:团队协作的智慧

4.1 分而治之的哲学

Fork/Join框架的核心理念:大事化小,小事并行,结果汇总

就像编写一本巨著:

  • 传统方式:一个人从头写到尾
  • Fork/Join方式:分给多个作者同时写不同章节,最后汇总

4.2 工作窃取算法:聪明的互助团队

public class TeamWorkExample {public void workStealingInAction() {// 初始:4个工人,每人25个任务// 工人A先完成自己的任务// 工人B还有10个任务没完成// 工作窃取:工人A从工人B的任务列表"偷"任务帮忙// 结果:整体效率最大化,没有人闲着}
}

4.3 实战示例:并行数组求和

/*** 使用Fork/Join并行计算数组和* 像团队协作完成大项目*/
public class ParallelArraySum {static class SumTask extends RecursiveTask<Long> {private static final int THRESHOLD = 1000; // 阈值private final long[] array;private final int start, end;public SumTask(long[] array, int start, int end) {this.array = array; this.start = start; this.end = end;}@Overrideprotected Long compute() {// 如果任务足够小,直接计算if (end - start <= THRESHOLD) {long sum = 0;for (int i = start; i < end; i++) sum += array[i];return sum;}// 拆分成两个子任务int mid = (start + end) / 2;SumTask leftTask = new SumTask(array, start, mid);SumTask rightTask = new SumTask(array, mid, end);// 并行执行:一个fork,一个当前线程执行leftTask.fork();long rightResult = rightTask.compute();long leftResult = leftTask.join();return leftResult + rightResult;}}public static void main(String[] args) {long[] array = new long[1000000];Arrays.fill(array, 1L); // 100万个1ForkJoinPool pool = new ForkJoinPool();long result = pool.invoke(new SumTask(array, 0, array.length));System.out.println("计算结果: " + result); // 输出: 1000000}
}

5. 性能对比与选择指南

5.1 不同场景的工具选择

使用场景 推荐工具 理由
高并发缓存 ConcurrentHashMap 分段锁,读多写少优化
任务队列 ConcurrentLinkedQueue 无锁,高吞吐量
资源池管理 LinkedBlockingQueue 阻塞操作,流量控制
优先级处理 PriorityBlockingQueue 按优先级排序
延时任务 DelayQueue 支持延时执行
直接传递 SynchronousQueue 零存储,直接传递
并行计算 Fork/Join框架 分治算法,工作窃取

5.2 性能优化要点

public class PerformanceTips {public void optimizationGuidelines() {// 1. 合理设置容量:避免频繁扩容或内存浪费// 2. 选择合适的队列:根据业务特性选择// 3. 避免过度同步:能用无锁就不用有锁// 4. 注意异常处理:并发环境下的异常传播// 5. 监控资源使用:避免内存泄漏和资源耗尽}
}

6. 最佳实践总结

6.1 设计原则

  1. 解耦生产消费:生产者专注生产,消费者专注消费
  2. 合理设置边界:防止资源耗尽,保证系统稳定性
  3. 优雅处理异常:不能让一个线程的异常影响整个系统
  4. 监控与调优:根据实际负载调整参数

6.2 常见陷阱与规避

public class CommonPitfalls {public void avoidTheseMistakes() {// ❌ 错误:在并发容器中执行耗时操作// ✅ 正确:快速完成容器操作,复杂逻辑异步处理// ❌ 错误:忽略容量边界导致内存溢出// ✅ 正确:合理设置容量,使用有界队列// ❌ 错误:依赖size()做业务判断// ✅ 正确:使用专门的状态变量// ❌ 错误:在Fork/Join任务中执行IO// ✅ 正确:Fork/Join只用于计算密集型任务}
}

结语:掌握并发编程的艺术

Java并发容器就像精心设计的交通系统,每种工具都在特定场景下发挥独特价值:

  • ConcurrentHashMap:智能的多车道高速公路
  • ConcurrentLinkedQueue:无锁的立体交通枢纽
  • 阻塞队列:有协调员的智能等待区
  • Fork/Join框架:团队协作的分布式工作模式

掌握这些工具,你就能构建出既安全又高效的并发程序,真正发挥多核硬件的威力。记住:合适的工具用在合适的场景,这才是并发编程的真谛。

现在,拿起这些利器,开始构建你的高性能并发应用吧!


进一步学习

  • Java并发编程实战
  • Java性能权威指南
  • 并发编程网

欢迎在评论区分享你的并发编程经验和问题!

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

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

相关文章

mysql报错many connections errors

mysql报错many connections errors如上图所示 首先使用可以访问数据库的主机进入数据库,我的mysql在linux系统中直接从Linux系统进入然后重新使用可视化工具进行连接即可!

2025薪酬管理系统推荐:6大主流系统全面对比与选型指南

引言:复杂多变的薪酬挑战与数字化破局之道 在 “降本增效”成为主旋律的2025年,中国企业面临的薪酬管理挑战愈发复杂和严峻。薪酬,作为企业人力资源管理的核心环节,不仅关乎员工的切身利益和组织士气,更是企业合规…

Solon (可替换 SpringBoot)集成 Docker 实战:30分钟搞定轻量级应用容器化部署

本文介绍了如何将Solon框架与Docker快速集成,突出了Solon在启动速度、内存占用和容器化方面的优势。文章从环境准备入手,详细说明了两种Docker打包方式(Maven插件和Dockerfile),提供了完整的配置示例和操作命令,…

vue2 组件封装 el-date-picker 日期

vue2 组件封装 el-date-picker 日期 基本使用都满足包括常用的:时间格式 :type [date,datetime,daterange ....]快捷方式 :日期左侧:如 今天,昨天,一个月前日期日期禁用:禁用日期段其它相关属性custom-date-pi…

我使用FHQ写了线段树2

虽然并没有任何的意义,但是我觉得很有意思,所以记录一下: #include <bits/stdc++.h> #define int long long using namespace std; const int MN=1e6+116; struct Node{int lc, rc, siz, rnd;int val, sum, a…

092_尚硅谷_for循环注意事项和细节(1)

092_尚硅谷_for循环注意事项和细节(1)1.for循环的第二种写法2.for循环的第三种写法_死循环3.for循环的第三种写法_死循环使用break终止循环

详细介绍:【网络通讯安全认证的理解:从密钥签名、数字证书到 HTTPS/TLS 流程】

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

VK36N5D 工作电压 2.2-5.5V 触摸芯片抗干扰5键触摸触控 5路触摸检测IC

VK36N5D具有5个触摸按键,可用来检测外部触摸按键上人手的触摸动作。该芯片具有较 高的集成度,仅需极少的外部组件便可实现触摸按键的检测。 提供了5个1对1输出脚,1个触摸状态输出脚,可通过IO脚选择上电输出电平和输…

魔兽争霸3冰封王座修改器 下载安装教程(图文步骤 + 功能详解)

魔兽争霸3冰封王座修改器下载与安装教程(适配1.24e~1.26版本),完整讲解安装方法、功能用法、快捷键操作、兼容性优化与常见问题解决方案。支持Windows 10 / 11系统,安全稳定。魔兽争霸3冰封王座修改器 下载安装教程…

Softmax回归模型

这段代码是一个完整的 Softmax回归模型 实现,用于解决 Fashion-MNIST数据集的图像分类问题。简单来说,它的作用是:让计算机通过学习大量衣服、鞋子等服饰图片,学会识别新的服饰图片属于哪一类(比如T恤、裤子、运动…

Oracle的connect by level在MySQL中的华丽变身 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

handsontable实现新增删除行(双行)

handsontable实现新增删除行(双行)// 配置方法const tableSettings = computed(() => {return {...hotTableParams,nestedHeaders: false,filters: false,columnSorting: false,height: 358,rowHeaders: false,co…

2025年国产角接触球轴承厂家推荐 一文了解轴承厂家选择标准

角接触球轴承在机械设备中的应用广泛,特别是精密机床、高速电机、电主轴等运行要求高的场合,更需要质量品质好一点的角接触轴承。想要轴承用的好,就得找到合适的生产厂家,下面就来推荐下2025年值得信任的国产角接触…

vxe-table 树形表格显示连接线的方式

vxe-table 树形表格显示连接线的方式 完整连接线 通过 tree-config.showLine 来启用是否显示连接线<template><div><vxe-grid v-bind="gridOptions"></vxe-grid></div> </…

2025年上海衣帽间定制机构权威推荐榜单:衣帽间设计/衣帽间十大品牌/衣帽间装修源头公司精选

在上海,一个规划合理的衣帽间正成为新兴住宅的标配。数据显示,2024年中国家装行业市场规模已突破860亿元,其中定制家具份额持续增长,而衣帽间作为定制家具的重要组成部分,正受到越来越多消费者的青睐。 01 行业趋…

在Web应用开发中状态到底是什么?

在计算机科学中,“状态”(State)这个词经常出现在讨论有状态(Stateful)和无状态(Stateless)系统、服务或组件时。要理解“状态”到底是什么,我们可以从最基本的层面来解释。一、什么是“状态”? 简单来说,“…

前后端不分离的springboot应用,静态文件修改了不更新的问题

当然,还有不依赖idea的解决方案,就是静态文件通过nginx来代理,直接将js和css这些文件代理到我们的代码目录,这样我们修改了代码目录后,配置就立马生效了。这样可以不依赖idea的版本,假如你的idea怎么设置热更新都…

Cookie与缓存的区别

一、本质定义 Cookie:客户端轻量化文本存储,存用户身份、网站偏好等会话相关数据,容量约4KB。 缓存:客户端/服务器临时存储,存网页静态资源(图、JS/CSS),容量几MB到几十GB。 二、3大核心区别 1. 存储内容:Coo…

2025 年铝卷厂家最新推荐榜,聚焦企业技术实力与市场口碑深度解析铝板铝卷/铝卷板/橘皮铝卷/压花铝卷/防锈铝卷/花纹铝卷公司推荐

引言 本次 2025 年铝卷产品推荐榜,由有色金属工业协会联合行业权威检测机构共同测评制定,测评过程严格遵循《铝及铝合金轧制卷材行业质量评价标准》。测评团队从企业生产实力、产品品质、服务能力三大维度入手,涵盖…

无人机航测界的强者——Pix4Dmapper 4.5.6使用教程+图文步骤

软件介绍 Pix4Dmapper 4.5.6是一款专业的无人机航空三维建模软件。它可以将通过无人机拍摄的照片转化为三维地图、模型、点云、高精度的数字高程模型(DEM)、数字表面模型(DSM)和正射影像(DOM)等。该软件具有自动…