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

ConcurrentHashMap

ConcurrentHashMap 是 Java 中用于在多线程环境下高效存储和操作键值对的哈希表实现,下面从基本概念、底层数据结构、线程安全机制、关键方法、性能特点以及使用场景几个方面详细介绍:

基本概念

ConcurrentHashMapjava.util.concurrent 包下的一个类,它继承自 AbstractMap 类并实现了 ConcurrentMap 接口。与 HashMap 不同,ConcurrentHashMap 是线程安全的,在多线程环境下可以高效地进行并发操作,避免了 HashMap 在多线程环境下可能出现的数据不一致和线程安全问题。

底层数据结构

JDK 1.7
  • 分段锁机制ConcurrentHashMap 使用分段锁(Segment)来实现线程安全。整个哈希表被分成多个 Segment,每个 Segment 类似于一个小的 HashMap,它继承自 ReentrantLock,可以独立加锁。不同的 Segment 可以被不同的线程同时访问,从而提高并发性能。
  • 数据结构:每个 Segment 内部包含一个哈希表,由数组和链表组成。
JDK 1.8
  • CAS + synchronized:摒弃了分段锁机制,采用 CAS(Compare-And-Swap,比较并交换)和 synchronized 来保证线程安全。
  • 数据结构:底层数据结构是数组 + 链表 + 红黑树。当链表长度超过 8 且数组长度大于 64 时,链表会转换为红黑树,以提高查找效率。

线程安全机制

JDK 1.7
  • 每个 Segment 都有自己独立的锁,不同的 Segment 可以并行操作。当一个线程访问某个 Segment 时,会对该 Segment 加锁,其他线程可以同时访问其他 Segment,从而提高并发度。
JDK 1.8
  • CAS 操作:在插入元素时,首先会使用 CAS 操作尝试更新数组中的节点,如果 CAS 操作成功,则插入成功;如果失败,则说明有其他线程在同时操作,会进入下一步处理。
  • synchronized 锁:当发生哈希冲突时,会使用 synchronized 对链表或红黑树的头节点加锁,保证同一时刻只有一个线程可以对该链表或红黑树进行操作。

关键方法

put(K key, V value)
  • 作用:将指定的键值对插入到 ConcurrentHashMap 中。
  • 实现:在 JDK 1.8 中,首先计算键的哈希值,找到对应的桶位置。如果桶为空,使用 CAS 操作将新节点插入;如果桶不为空,对桶的头节点加锁,遍历链表或红黑树,若键已存在则更新值,否则插入新节点。
get(Object key)
  • 作用:根据指定的键获取对应的值。
  • 实现:计算键的哈希值,找到对应的桶位置,然后遍历链表或红黑树查找键对应的值。由于 get 操作不需要加锁,所以性能较高。
size()
  • 作用:返回 ConcurrentHashMap 中键值对的数量。
  • 实现:在 JDK 1.8 中,size 方法会先尝试使用无锁的方式统计元素数量,如果失败则会加锁统计。

性能特点

  • 高并发性能:由于采用了分段锁(JDK 1.7)或 CAS + synchronized(JDK 1.8)的机制,ConcurrentHashMap 可以支持多个线程同时进行读写操作,并发性能较高。
  • 空间开销:相比于 HashMapConcurrentHashMap 为了保证线程安全,会有一定的空间开销,例如分段锁(JDK 1.7)和额外的 CAS 操作。

使用场景

  • 多线程环境下的缓存:在多线程环境中,如果需要使用缓存来存储数据,ConcurrentHashMap 是一个不错的选择,它可以保证线程安全,同时具有较高的并发性能。
  • 共享数据存储:当多个线程需要共享一个哈希表时,使用 ConcurrentHashMap 可以避免数据不一致和线程安全问题。

示例代码

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 插入键值对
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("cherry", 3);

        // 获取值
        Integer value = map.get("banana");
        System.out.println("Value of banana: " + value);

        // 遍历键值对
        for (ConcurrentHashMap.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // 删除键值对
        map.remove("cherry");
        System.out.println("After removing cherry, size: " + map.size());
    }
}

通过上述代码可以看到,ConcurrentHashMap 的使用方式与 HashMap 类似,但它在多线程环境下可以保证线程安全。

相关文章:

  • 第七章 activiti流程 “容器融合控制室”
  • 论合理利润空间促进社会繁荣
  • alibaba商品数据采集实战:Python接口调用+反爬策略破解(2025最新版)
  • fluent-ffmpeg 依赖详解
  • Mybatis做批量操作
  • ST-LINK端口连接失败,启动GDB server失败的问题处理方法,有效
  • python容器之常用操作
  • 为AI聊天工具添加一个知识系统 之127 详细设计之68 编程 核心技术:Cognitive Protocol Language 之1
  • openEuler环境下GlusterFS分布式存储集群部署指南
  • 【FL0086】基于SSM和微信小程序的垃圾分类小程序
  • OpenFeign:服务间通讯携带 Token 的实现
  • 本地大模型搭建与webui交互
  • 我和我的通义灵码
  • LeetCode:131. 分割回文串(DP Java)
  • 8 - PS XADC接口实验
  • Java 大视界 -- Java 大数据机器学习模型的可解释性增强技术与应用(107)
  • nist关于rsa中p,q的要求
  • 【数据挖掘】Pandas
  • 【开源免费】基于SpringBoot+Vue.JS网络海鲜市场系统(JAVA毕业设计)
  • 看得见摸得着的AI:具身智能
  • c 怎么做网站/购买链接怎么买
  • 网站商城怎么做app/百度精准搜索
  • 做网站学什么语言好/网店代运营公司靠谱吗
  • 网站的内链优化怎样做/北京seo推广系统
  • 做钓鱼网站论坛/营销战略有哪些内容
  • 阿坝州住房和城乡建设厅网站/百度网盘人工客服电话多少