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

ConcurrentHashMap的使用

ConcurrentHashMap概述

ConcurrentHashMap是Java 并发包(java.util.concurrent)中提供的一个线程安全且高效的哈希表实现,用于在并发环境中存储键值对,它允许在多个线程之间安全地共享和修改数据,使得开发者无需显式同步代码就能在并发环境下安全使用。与同样是线程安全的哈希表HashTable相比,ConcurrentHashMap具有更高的并发效率。

ConcurrentHashMap的实现

Java7中的实现

        在 Java7中,ConcurrentHashMap使用了分段锁(Segment)的技术来实现并发访问的安全性。这个设计思想是将整个ConcurrentHashMap分成若干个Segment(默认为16),每个Segment相当于一个小型的哈希表,拥有自己的锁。这样,在进行put操作时,只需要锁定当前操作Segment而不是整个 Map,多个线程就能同时操作不同的段,在并发环境下将实现更高的吞吐量,而在单线程环境下只损失非常小的性能。Segment使用可重入锁ReentrantLock实现。

Java8中的实现

        在 Java8中对ConcurrentHashMap进行了重大改进,具体包括进一步细化了锁粒度,摒弃了原有的分段锁的设计,转而采用了CAS+synchronized的同步方式,锁住的不再是一个段,而是某个节点,即只有HashCode相同的元素才可能阻塞,进一步提高了并发性能。与HashMap一样,Java8中ConcurrentHashMap底层数据结构也由数组+链表改为了数组+链表+红黑树。至于引入红黑树的理由我想和HashMap是一样的。之前写了一篇关于HashMap文章有详细介绍,请参考:【Java集合】HashMap

示例代码

ConcurrentHashMap使用增强for循环或forEach遍历集合时可以删除元素,而不像HashMap、ArrayList等其它集合需要使用迭代器。遍历集合时删除元素问题

public static void main(String[] args) {Map<String, Integer> conMap = new ConcurrentHashMap<>();for (int i = 0; i < 10; i++) {conMap.put("key"+i, i);}for (Map.Entry<String, Integer> entry : conMap.entrySet()) {int v = entry.getValue();if (v < 5) {conMap.remove(entry.getKey());}}System.out.println(conMap);}
//输出
{key5=5, key6=6, key9=9, key7=7, key8=8}

一个线程对ConcurrentHashMap执行插入,另一个线程可以实时读取,ConcurrentHashMap保证了线程之间的安全性和可见性。

public static void main(String[] args) {Map<String, Integer> conMap = new ConcurrentHashMap<>();Thread thread1 = new Thread(() -> {for (int i = 0; i < 10; i++) {conMap.put("key"+i, i);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}});Thread thread2 = new Thread(() -> {while (true){System.out.println("size="+conMap.size());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}});thread1.start();thread2.start();
}
//输出
size=0
size=1
size=2
size=3
size=4
size=5
size=6
size=7
size=8
size=9
size=10
size=10
size=10
...

总结

总之ConcurrentHashMap是一个高性能的Java并发容器,是多线程下常用的map容器,其使用方法基本可以参考HashMap。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 如何选择光伏业务监管系统软件
  • 2024.09.18 leetcode 每日一题
  • 排序算法C++
  • AWS EKS 中的负载均衡和 TLS 配置:全面指南
  • Matplotlib-数据可视化详解
  • QT| QT配置CUDA
  • R语言APSIM模型进阶应用与参数优化、批量模拟实践技术
  • C++(学习)2024.9.23
  • ubuntu如何进行切换内核版本全教程
  • LLM - 理解 多模态大语言模型(MLLM) 的 幻觉(Hallucination) 与相关技术 (七)
  • leetcode91. 解码方法,动态规划
  • 最新Kali Linux超详细安装教程(附镜像包)
  • 『C/C++』整型和字符串相互转换
  • itextsharp报错 PdfReader not opened with owner password
  • 【51实物与仿真】基于51单片机设计的波形/函数发生器(正弦波、锯齿波、三角波、矩形波,设定频率步进值,改变振幅,LCD显示)——文末完整资料链接
  • 分享的文章《人生如棋》
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • 08.Android之View事件问题
  • Docker下部署自己的LNMP工作环境
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • MobX
  • PAT A1120
  • uva 10370 Above Average
  • vue-loader 源码解析系列之 selector
  • webpack4 一点通
  • Zepto.js源码学习之二
  • 聊聊redis的数据结构的应用
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 如何选择开源的机器学习框架?
  • 十年未变!安全,谁之责?(下)
  • 首页查询功能的一次实现过程
  • 为什么要用IPython/Jupyter?
  • nb
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • 阿里云移动端播放器高级功能介绍
  • 数据可视化之下发图实践
  • ​​​【收录 Hello 算法】9.4 小结
  • ​埃文科技受邀出席2024 “数据要素×”生态大会​
  • #HarmonyOS:基础语法
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (arch)linux 转换文件编码格式
  • (C++)八皇后问题
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (接口自动化)Python3操作MySQL数据库
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (三)SvelteKit教程:layout 文件
  • (四) 虚拟摄像头vivi体验
  • (原)本想说脏话,奈何已放下
  • (转)linux下的时间函数使用
  • (转)关于多人操作数据的处理策略
  • (转载)利用webkit抓取动态网页和链接