ConcurrentHashMap的相关介绍和使用

概述

ConcurrentHashMap是Java中提供的一个关于线程安全的哈希表实现,他是java.util.concurrent包的一部分,允许多个读操作并发进行,提高了并发环境下的性能。ConcurrentHashMap实现了ConcurrentMap接口,故而他也有ConcurrentMap中的所有原子操作,例如putIfAbsentremovereplace

ConcurrentMap定义了一些重要的线程安全的原子操作,而ConcurrentHashMap提供了这些操作的具体实现。因此,ConcurrentHashMap继承了ConcurrentMap的所有特性,并且在此基础上进行了优化和扩展,以支持更高效的并发操作。

在这里插入图片描述

在这里插入图片描述

底层实现

在Java8之前,ConcurrentHashMap使用分段技术,将数据分成一段一段,没一段都由自己的锁,当一个线程访问一个特定的段时候,只会锁定这个段,而不会影响其他段,这样就允许多个线程并发地访问不同的段。

在Java8的时候,ConcurrentHashMap的实现被重写了,不在使用分段锁,使用了一种基于节点的锁定策略,通过使用CAS(compare and Swap) 操作和synchronized关键字来减少锁的争用。在Java 8中,ConcurrentHashMap的数据结构是一个数组 + 链表 + 红黑树的复合结构,当链表长度超过一定的阈值时候,链表会转换为红黑树,从而提高搜索效率。

优缺点

优点

  • 线程安全: 提供了线程安全的Map实现,适用于多线程环境。
  • 高并发性能:相比于Hashtable和Collections.synchronizedMap,ConcurrentHashMap提供了更好的并发性能。
  • 拓展性: 通过分离锁的机制,允许更多的并发更新操作。
  • 原子操作:支持多种原子操作,简化了并发编程。

缺点

  • 内存占用: 为了实现线程安全,可能会比非线程安全的Map实现使用更多的内存。
  • 复杂性:内部实现比较复杂,理解和使用不当会导致性能问题。

案例:

模拟实现一个简单的线程安全的缓存系统

import java.util.concurrent.ConcurrentHashMap;

public class SimpleCache<K, V> {
    private final ConcurrentHashMap<K, V> cacheMap = new ConcurrentHashMap<>();

    public V get(K key) {
        return cacheMap.get(key);
    }

    public void put(K key, V value) {
        cacheMap.put(key, value);
    }

    public void remove(K key) {
        cacheMap.remove(key);
    }

    // 其他可能的缓存操作...
}

public class CacheDemo {
    public static void main(String[] args) {
        SimpleCache<String, String> cache = new SimpleCache<>();

        // 添加缓存项
        cache.put("key1", "value1");

        // 从缓存中读取项
        String value = cache.get("key1");
        System.out.println("Cached value for key1: " + value);

        // 删除缓存项
        cache.remove("key1");
    }
}

在案例中,我们创建了一个名为SimpleCache的类,它使用ConcurrentHashMap来存储缓存项。这个简单的缓存系统是线程安全的,可以在多线程环境中使用,而不需要担心数据的一致性问题。

用来解决什么问题

ConcurrentHashMap通常用于解决需要高并发读写操作的场景,例如缓存系统、会话存储、共享资源的访问控制等。

示例代码:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class SimpleConcurrentCache<K, V> {
    private final ConcurrentHashMap<K, V> cacheMap = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<K, ReentrantLock> lockMap = new ConcurrentHashMap<>();

    public V get(K key) {
        return cacheMap.get(key);
    }

    public void put(K key, V value) {
        cacheMap.put(key, value);
    }

    public void remove(K key) {
        cacheMap.remove(key);
    }

    // 获取资源的访问锁
    public ReentrantLock getLock(K key) {
        // 使用 putIfAbsent 保证只有一个锁实例被创建
        lockMap.putIfAbsent(key, new ReentrantLock());
        return lockMap.get(key);
    }

    // 用于会话存储的方法
    public void storeSession(K sessionId, V sessionData) {
        put(sessionId, sessionData);
    }

    public V retrieveSession(K sessionId) {
        return get(sessionId);
    }

    public void removeSession(K sessionId) {
        remove(sessionId);
    }

    // 用于共享资源访问控制的方法
    public void accessResource(K resourceId, Runnable accessLogic) {
        ReentrantLock lock = getLock(resourceId);
        lock.lock();
        try {
            // 执行访问资源的逻辑
            accessLogic.run();
        } finally {
            lock.unlock();
        }
    }
}
public class CacheDemo {
    public static void main(String[] args) {
        SimpleConcurrentCache<String, String> cache = new SimpleConcurrentCache<>();

        // 存储会话数据
        cache.storeSession("user1_session", "User 1 Session Data");

        // 访问会话数据
        String sessionData = cache.retrieveSession("user1_session");
        System.out.println("Retrieved session data: " + sessionData);

        // 访问共享资源
        cache.accessResource("shared_resource", () -> {
            // 这里是访问共享资源的逻辑
            System.out.println("Accessing shared resource");
        });

        // 移除会话数据
        cache.removeSession("user1_session");
    }
}

SimpleConcurrentCache类使用ConcurrentHashMap来存储缓存数据和锁对象。我们为每个资源创建了一个ReentrantLock,以便在访问共享资源时提供同步控制。这样,我们可以确保在访问共享资源时,每次只有一个线程可以执行访问逻辑。

storeSessionretrieveSessionremoveSession方法提供了会话存储的基本操作。accessResource方法允许线程安全地访问共享资源,它首先获取资源对应的锁,然后执行访问逻辑,并在最后释放锁。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024.3.18

1、试编程 封装一个动物的基类&#xff0c;类中有私有成员:姓名&#xff0c;颜色&#xff0c;指针成员年纪再封装一个狗这样类&#xff0c;共有继承于动物类&#xff0c;自己拓展的私有成员有:指针成员:腿的个数(整型intcount)&#xff0c;共有成员函数:会叫:void speak() 要求…

ardupilot开发 --- 机载(边缘)计算机-VISP 篇

啊啊啊我的妻王氏宝钏 1. 一些概念 1. 一些概念 什么是VISP VISP即Visual servoing platform. Allows to control a robot equipped with a camera from measures extracted from the images.实现无人机飞行控制&#xff0c;机器人运动控制。实现实时目标检测。实现实时位姿估…

SpringCloud Sleuth 分布式请求链路跟踪

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十篇&#xff0c;即介绍 Sleuth 分布式请求链路跟踪。 二、概述 2.1 出现的原因 在微服务框架中&…

什么是IoT物联网平台?

在数字化浪潮的席卷下&#xff0c;物联网&#xff08;IoT&#xff09;技术逐渐渗透到我们生活的方方面面&#xff0c;从智能家居到智慧城市&#xff0c;从工业自动化到智能农业&#xff0c;IoT正以其独特的魅力改变着世界。然而&#xff0c;当我们谈论IoT时&#xff0c;我们究竟…

maven一点通

1.maven简介 Maven是一个基于Java的工程构建工具&#xff0c;用于管理和构建项目的依赖关系。它提供了一种标准的项目结构和一组约定&#xff0c;使得项目的开发、构建、部署和文档化更加容易和可靠。 Maven的主要功能包括&#xff1a; 依赖管理&#xff1a;Maven可以自动下载…

elementui el-table表格自动循环滚动【超详细图解】

效果如图 1. 当表格内容超出时&#xff0c;自动滚动&#xff0c;滚动到最后一条之后在从头滚动。 2. 鼠标移入表格中&#xff0c;停止滚动&#xff1b;移出后&#xff0c;继续滚动。 直接贴代码 <template><div><div class"app-container"><e…

蓝桥杯前端Web赛道-输入搜索联想

蓝桥杯前端Web赛道-输入搜索联想 题目链接&#xff1a;1.输入搜索联想 - 蓝桥云课 (lanqiao.cn) 题目要求&#xff1a; 题目中还包含effect.gif 更详细的说明了需求 那么观察这道题需要做两件事情 把表头的每一个字母进行大写进行模糊查询 这里我们会用到几个js函数&#…

matlab FR共轭梯度法求解无约束问题

1、内容简介 略 75-可以交流、咨询、答疑 matlab FR共轭梯度法求解无约束问题 一维搜索 黄金搜索到单峰&#xff0c;单变量最小值 2、内容说明 略 Fletcher-Reeves共轭梯度法&#xff0c;简称FR法。 共轭梯度法的基本思想是把共轭性与最速下降方法相结合&#xff0c;利用…

rt-thread之通讯协议modbus软件包的使用记录(lwip+modbus组合)

前言 使用freemodbus软件包使用网口通讯(sallwip)ip地址使用dhcp动态获取 软件包 相关宏定义 /*-----------------------------------------NET 宏定义-------------------------------------------*/#define RT_USING_SAL #define SAL_INTERNET_CHECK /* Docking with prot…

mysqlcheck 数据完整性检查与修复

目录 mysqlcheck 命令文档 描述 选项 参数 示例 mysqlcheck 命令文档 mysqlcheck 是MySQL提供的一个工具&#xff0c;用于检查、修复、优化和分析数据库和表的健康状态。你可以使用它来确保数据库表的完整性和性能。 mysqlcheck [options] db_name [tbl_name ...]mysqlch…

德迅蜂巢(容器安全)全面出击

随着云计算的发展&#xff0c;以容器和微服务为代表的云原生技术&#xff0c;受到了人们的广泛关注&#xff0c;德迅云安全德迅蜂巢&#xff08;容器安全&#xff09;是企业容器运行时和容器编排的首要选择。然而&#xff0c;在应用容器过程中&#xff0c;大多数企业都遇到过不…

分数相加减(C语言)

一、流程图&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int fenmu 2;int result 1;int fuhao 1;//执行循环&#xff1b;while (fenmu < 100){//运算&#xff1b;fuhao (-1…

TSINGSEE青犀AI智能分析网关V4酿酒厂安全挂网AI检测算法

在酿酒行业中&#xff0c;安全生产一直是企业经营中至关重要的一环。为了确保酒厂生产过程中的安全&#xff0c;TSINGSEE青犀AI智能分析网关V4的安全挂网AI检测算法发挥了重要作用。 TSINGSEE青犀AI智能分析网关V4的安全挂网检测算法是针对酒厂里酒窖挂网行为进行智能检测与识…

[java基础揉碎]Object类详解

目录 equals方法: hashCode: toString: finalize: equals方法: 和equals对比 1.: 既可以判断基本类型&#xff0c;又可以判断引用类型 2.: 如果判断基本类型&#xff0c;判断的是值是否相等。示例: int i10; double d10.0; 3.:如果判断引用类型&#xff0c;判断的是地址是…

SQLiteC/C++接口详细介绍sqlite3_stmt类简介

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十八&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;一&#xff09; 预准备语句对象 typedef struct sqlite3_stmt sqlite3_stmt…

关于安卓USB开发(一)文件复制,文件夹创建

背景 在安卓应用中&#xff0c;把某个文件&#xff0c;复制到插入的U盘中 开发环境 win10,jdk8,as4 测试机型 红米Note11&#xff0c;android13 源码问题 文末将会提供博主整合好的源码项目连接&#xff0c;以供学习交流 注意 本次实战&#xff0c;u盘格式是fat32&…

弗洛伊德-华沙算法求任意两点之间的最短路径算法

对于弗洛伊德-华沙算法首先是要假设研究的图中是不包含有负边的&#xff0c;对于所给的图中的任意亮点v1&#xff0c;vm&#xff0c;假设两点之间存在一条连通路径&#xff0c;对于该路径中去掉头和尾节点&#xff0c;也就是v1&#xff0c;vm&#xff0c;剩下的节点也就称之为这…

【MySQL】2. 数据库基础

1. 数据库基础&#xff08;重点&#xff09; 1.1 什么是数据库 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件保存数据有以下几个缺点&#xff1a; 文件的安全性问题 文件不利于数据查询和管理 文件不利于存储海量数据 文件在程序中控制不方便 数据库存储介…

告别紧张,轻松应对!公众演讲的实用技巧

告别紧张&#xff0c;轻松应对&#xff01;公众演讲的实用技巧 公众演讲&#xff0c;对于许多人来说&#xff0c;是一项充满挑战的任务。面对众多的听众&#xff0c;紧张情绪往往难以避免&#xff0c;甚至可能影响到演讲的效果。然而&#xff0c;通过掌握一些实用的技巧&#…

常见的业务场景实现方案

1.解决请求服务器接口跨域的问题 本地项目请求服务器接口时&#xff0c;因为客户端的同源策略&#xff0c;导致了跨域问题 配置允许本地跨域&#xff1a; /api指代我们要请求的接口域名&#xff0c;例如&#xff1a;this.$axios.get(/api/app.php?mApp&cIndex&aind…