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

JAVA基础 - 高效管理线程隔离数据结构ThreadLocalMap

欢迎光临小站:致橡树

ThreadLocalMapThreadLocal 的核心底层数据结构,负责在每个线程中存储与 ThreadLocal 实例绑定的数据。它的设计目标是高效管理线程隔离数据,同时尽量减少内存泄漏风险。以下是其核心实现细节。

数据结构与设计目标

核心结构

  • Entry 数组
    ThreadLocalMap 内部维护一个 Entry[] 数组,每个 Entry 表示一个键值对。

    static class Entry extends WeakReference<ThreadLocal<?>> {Object value; // 值(强引用)Entry(ThreadLocal<?> k, Object v) {super(k); // Key 是弱引用(继承自 WeakReference)value = v;}
    }
    • KeyThreadLocal 实例(弱引用,避免内存泄漏)。

    • Value:线程绑定的数据(强引用,需手动或惰性清理)。

  • 哈希算法
    通过 ThreadLocal.threadLocalHashCode 计算索引位置(类似取模运算):

    int i = key.threadLocalHashCode & (table.length - 1); // table.length 是 2 的幂

设计目标

  • 线程隔离:每个线程独立维护自己的 ThreadLocalMap

  • 内存高效:通过弱引用和惰性清理减少内存泄漏。

  • 低冲突率:使用线性探测法(开放寻址)处理哈希冲突。

哈希冲突解决:开放寻址法(线性探测法)

HashMap 的链表法不同,ThreadLocalMap 使用 开放寻址法(线性探测法) 解决冲突:

  1. 插入流程

    • 计算初始索引 i = hash & (len-1)

    • table[i] 已被占用(Key 不同),则向后遍历(i = nextIndex(i, len))直到找到空槽。

  2. 查找流程

    • 计算初始索引 i,若 table[i] 的 Key 不匹配,则向后遍历直到找到目标或空槽。

  3. 删除流程

    • 清理当前槽位,并触发探测式清理(expungeStaleEntry),避免后续查找因空槽中断。

示例:插入一个 Key 到冲突位置

// 假设 table[3] 已被占用,Key 不同
hash = key.threadLocalHashCode;
i = hash & (len-1); // 初始计算为 3
while (table[i] != null) {i = nextIndex(i, len); // 线性探测,i=4,5,6...
}
table[i] = new Entry(key, value);

内存管理机制

惰性清理(Lazy Cleanup)

在以下操作中触发清理无效 Entry(Key 为 null 的 Entry):

  • getEntry(ThreadLocal<?> key):查找时发现 Key 已被回收,触发清理。

  • set(ThreadLocal<?> key, Object value):插入时遇到无效 Entry,触发清理。

  • remove(ThreadLocal<?> key):直接清理指定 Entry。

核心方法 expungeStaleEntry(int staleSlot)

private int expungeStaleEntry(int staleSlot) {Entry[] tab = table;int len = tab.length;// 1. 清理当前槽位tab[staleSlot].value = null;tab[staleSlot] = null;size--;// 2. 向后探测清理连续段中的无效 EntryEntry e;int i;for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {ThreadLocal<?> k = e.get();if (k == null) {e.value = null;tab[i] = null;size--;} else {int h = k.threadLocalHashCode & (len - 1);if (h != i) { // 该 Entry 本应位于其他位置(因冲突被挤到此处)tab[i] = null; // 清空当前槽位// 重新哈希到正确位置while (tab[h] != null) h = nextIndex(h, len);tab[h] = e;}}}return i;
}

扩容机制

  • 触发条件
    当插入新 Entry 后 size >= threshold(阈值 = 容量 * 2/3),惰性清理后仍无法腾出空间。

  • 扩容流程

    1. 容量翻倍(如 16 → 32),创建新数组。

    2. 遍历旧数组,重新哈希有效 Entry 到新数组。

    3. 更新阈值(新容量 * 2/3)。

与 HashMap 的对比

特性

ThreadLocalMap

HashMap

数据结构

Entry 数组(开放寻址法)

数组 + 链表/红黑树

Key 引用类型

弱引用(WeakReference)

强引用

哈希冲突解决

线性探测法

链表法或红黑树

线程安全

线程隔离(无需同步)

非线程安全(ConcurrentHashMap 是线程安全的)

内存管理

惰性清理 + 弱引用

依赖 GC 或手动移除

扩容触发条件

基于有效 Entry 数量(清理后)

基于总 Entry 数量

典型应用场景

  1. 线程隔离数据存储

    • 每个线程的数据库连接、事务上下文等。

  2. 性能优化

    • 避免线程间竞争(如 SimpleDateFormat 的线程安全封装)。

  3. 框架级使用

    • Spring 的 RequestContextHolderTransactionSynchronizationManager

注意事项与最佳实践

  1. 避免内存泄漏

    • 使用完 ThreadLocal 后必须调用 remove(),尤其是线程池环境。

    • 避免使用静态 ThreadLocal(静态变量强引用 Key,导致弱引用失效)。

  2. 减少哈希冲突

    • 控制每个线程的 ThreadLocal 实例数量。

  3. 谨慎扩容

    • 频繁扩容会影响性能,初始化时预估合理容量。

总结

ThreadLocalMapThreadLocal 实现线程隔离存储的核心,其通过 弱引用 Key开放寻址法(线性探测法)惰性清理机制,在保证高效访问的同时降低内存泄漏风险。开发者需理解其底层逻辑,正确使用 remove() 方法,才能在高并发场景下安全高效地管理线程局部变量。

相关文章:

JAVA基础 - 高效管理线程隔离数据结构ThreadLocalMap

欢迎光临小站&#xff1a;致橡树 ThreadLocalMap 是 ThreadLocal 的核心底层数据结构&#xff0c;负责在每个线程中存储与 ThreadLocal 实例绑定的数据。它的设计目标是高效管理线程隔离数据&#xff0c;同时尽量减少内存泄漏风险。以下是其核心实现细节。 数据结构与设计目标…...

DeepSeek 接入 Word 完整教程

一、前期准备 1.1 注册并获取 API 密钥 访问 DeepSeek 平台&#xff1a; 打开浏览器&#xff0c;访问 DeepSeek 官方网站&#xff08;或您使用的相应平台&#xff09;。注册并登录您的账户。 创建 API 密钥&#xff1a; 在用户控制面板中&#xff0c;找到“API Keys”或“API…...

通义灵码助力Neo4J开发:快速上手与智能编码技巧

在 Web 应用开发中&#xff0c;Neo4J 作为一种图数据库&#xff0c;用于存储节点及节点间的关系。当图结构复杂化时&#xff0c;关系型数据库的查找效率会显著降低&#xff0c;甚至无法有效查找&#xff0c;这时 Neo4J 的优势便凸显出来。然而&#xff0c;由于其独特的应用场景…...

高性能文件上传服务

高性能文件上传服务 —— 您业务升级的不二选择 在当今互联网数据量激增、文件体积日益庞大的背景下&#xff0c;高效、稳定的文件上传方案显得尤为重要。我们的文件分块上传服务端采用业界领先的 Rust HTTP 框架 Hyperlane 开发&#xff0c;凭借其轻量级、低延时和高并发的特…...

p2p的发展

PCDN&#xff08;P2P内容分发网络&#xff09;行业目前处于快速发展阶段&#xff0c;面临机遇与挑战并存的局面。 一、发展机遇 技术融合推动 边缘计算与5G普及&#xff1a;5G的高带宽、低延迟特性与边缘计算技术结合&#xff0c;显著提升PCDN性能&#xff0c;降低延迟&#x…...

Java Lambda 表达式详解:发展史、语法、使用场景及代码示例

Java Lambda 表达式详解&#xff1a;发展史、语法、使用场景及代码示例 1. Lambda 表达式的发展史 背景与动机 JDK 7 前&#xff1a;Java的匿名内部类虽强大&#xff0c;但代码冗余&#xff08;如事件监听器、集合遍历&#xff09;。JDK 8&#xff08;2014&#xff09;&#…...

【从0到1学Elasticsearch】Elasticsearch从入门到精通(下)

我们在【从0到1学Elasticsearch】Elasticsearch从入门到精通&#xff08;上&#xff09;这边文章详细讲解了如何创建索引库和文档及javaAPI操作&#xff0c;但是在实战当中&#xff0c;我们还需要根据一些特殊字段对文档进行查找搜索&#xff0c;仅仅靠id查找文档是显然不够的。…...

Python实现贪吃蛇二

上篇文章Python实现贪吃蛇一&#xff0c;实现了一个贪吃蛇的基础版本&#xff0c;但存在一些不足&#xff0c;也缺乏一些乐趣。本篇文章将对其进行一些改进&#xff0c;主要修改/实现以下几点&#xff1a; 1、解决食物随机生成的位置与蛇身重合问题 2、蛇身移动加速/减速功能 3…...

使用pybind11开发c++扩展模块输出到控制台的中文信息显示乱码的问题

使用pybind11开发供Python项目使用的C++扩展模块时,如果在扩展模块的C++代码中向控制台输出的信息中包含中文,python程序的控制台很容易出现乱码。以如下C++扩展框架代码为例(这是对上一篇文章简明使用pybind11开发pythonc+扩展模块教程-CSDN博客中的C++扩展框架代码进行少量…...

基于51单片机的正负5V数字电压表( proteus仿真+程序+设计报告+讲解视频)

基于51单片机的正负5V数字电压表( proteus仿真程序设计报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0101 1. 主要功能&#xff1a; 设计一个基于51单片机数字电压表 1、能够…...

Java雪花算法

以下是用Java实现的雪花算法代码示例&#xff0c;包含详细注释和异常处理&#xff1a; 代码下面有解析 public class SnowflakeIdGenerator {// 起始时间戳&#xff08;2020-01-01 00:00:00&#xff09;private static final long START_TIMESTAMP 1577836800000L;// 各部分…...

前端大屏可视化项目 局部全屏(指定盒子全屏)

需求是这样的&#xff0c;我用的项目是vue admin 项目 现在需要在做大屏项目 不希望显示除了大屏的其他东西 于是想了这个办法 至于大屏适配问题 请看我文章 底部的代码直接复制就可以运行 vue2 px转rem 大屏适配方案 postcss-pxtorem-CSDN博客 <template><div …...

Android studio消息同步机制:消息本地存储,服务器交互减压

文章目录 后端&#xff08;Flask&#xff09;代码前端&#xff08;Android Studio Java&#xff09;代码同步机制1. 放在 Activity 中2. 放在 Service 中3. 放在 DataManager 类中 放在Service中的具体实现1. 后台执行2. 独立于活动3. 系统管理4. 绑定服务5. 进程间通信&#x…...

P8667 [蓝桥杯 2018 省 B] 递增三元组(摘自洛谷)

给定三个整数数组 A[A1​,A2​,⋯,AN​]&#xff0c;B[B1​,B2​,⋯,BN​]&#xff0c;C[C1​,C2​,⋯,CN​]。 请你统计有多少个三元组 (i,j,k) 满足&#xff1a; 1≤i,j,k≤NAi​<Bj​<Ck​ 输入格式 第一行包含一个整数 N。 第二行包含 N 个整数 A1​,A2​,⋯,AN…...

【Kafka基础】监控与维护:动态配置管理,灵活调整集群行为

1 基础配置操作 1.1 修改主题保留时间 /export/home/kafka_zk/kafka_2.13-2.7.1/bin/kafka-configs.sh --alter \--bootstrap-server 192.168.10.33:9092 \--entity-type topics \--entity-name yourtopic \--add-config retention.ms86400000 参数说明&#xff1a; retention…...

01_JDBC

文章目录 一、概述1.1、什么是JDBC1.2、JDBC原理 二、JDBC入门2.1、准备工作2.1.1、建库建表2.1.2、新建项目 2.2、建立连接2.2.1、准备四大参数2.2.2、加载驱动2.2.3、准备SQL语句2.2.4、建立连接2.2.5、常见问题 2.3、获取发送SQL的对象2.4、执行SQL语句2.5、处理结果2.6、释…...

STM32 HAL库 HC - SR04 超声波测距模块驱动实现

一、引言 在现代嵌入式系统开发中&#xff0c;传感器技术起着至关重要的作用。超声波测距模块作为一种常用的距离测量传感器&#xff0c;因其成本低、精度较高、使用方便等优点&#xff0c;被广泛应用于机器人避障、液位检测、工业自动化等领域。HC - SR04 超声波测距模块是一…...

Spring Boot 热部署详解,包含详细的配置项说明

Spring Boot 热部署详解 1. 热部署简介 热部署&#xff08;Hot Deployment&#xff09;允许在应用运行时修改代码或配置文件&#xff0c;无需重启应用即可使更改生效。Spring Boot 通过 spring-boot-devtools 模块实现这一功能&#xff0c;其核心依赖于 LiveReload 技术和自动…...

剑指Offer(数据结构与算法面试题精讲)C++版——day12

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day12 题目一&#xff1a;小行星碰撞题目二&#xff1a;每日温度题目三&#xff1a;直方图最大矩形面积附录&#xff1a;源码gitee仓库 题目一&#xff1a;小行星碰撞 题目&#xff1a;输入一个表示小行星的数…...

贪心算法(18)(java)距离相等的条形码

在一个仓库里&#xff0c;有一排条形码&#xff0c;其中第 i 个条形码为 barcodes[i]。 请你重新排列这些条形码&#xff0c;使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案&#xff0c;此题保证存在答案。 示例 1&#xff1a; 输入&#xff1a;barco…...

Docker学习笔记-docker安装、删除

一、在centOS 7中docker的默认安装目录 # Docker 主配置文件目录 ls /etc/docker# Docker 数据目录&#xff08;镜像、容器、卷等&#xff09; ls /var/lib/docker# Docker 可执行文件路径 which docker # 输出类似 /usr/bin/docker 二、docker文件目录说明 目录/文件用途/…...

【Python 开源】你的 Windows 关机助手——PyQt5 版定时关机工具

&#x1f5a5;️ 你的 Windows 关机助手——PyQt5 版定时关机工具 相关资源文件已经打包成EXE文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着开源精神的…...

STM32 HAL库 ADC+TIM+DMA 3路 1S采样一次电压

一、引言 在很多嵌入式系统应用中&#xff0c;需要对多路模拟信号进行周期性采样&#xff0c;例如在工业控制、环境监测等领域。STM32F407 是一款高性能的微控制器&#xff0c;其丰富的外设资源可以方便地实现这样的功能。通过结合 ADC&#xff08;模拟 - 数字转换器&#xff…...

汉诺塔问题——用贪心算法解决

目录 一&#xff1a;起源 二&#xff1a;问题描述 三&#xff1a;规律 三&#xff1a;解决方案 递归算法 四&#xff1a;代码实现 复杂度分析 一&#xff1a;起源 汉诺塔&#xff08;Tower of Hanoi&#xff09;问题起源于一个印度的古老传说。在世界中心贝拿勒斯&#…...

【Python爬虫】简单介绍

目录 一、基本概念 1.1 什么是爬虫 1.2 Python为什么适合爬虫 1.3 Python爬虫应用领域 &#xff08;1&#xff09;数据采集与分析 市场调研 学术研究 &#xff08;2&#xff09;内容聚合与推荐 新闻聚合 视频内容聚合 &#xff08;3&#xff09;金融领域 股票数据获…...

使用MCP服务通过自然语言操作数据库(vscode+cline版本)

使用MCP服务操纵数据库(vscodecline版本) 本文主要介绍&#xff0c;在vscode中使用cline插件调用deepseek模型&#xff0c;通过MCP服务器 使用自然语言去操作指定数据库。本文使用的是以己经创建号的珠海航展数据库。 理解MCP服务&#xff1a; MCP&#xff08;Model Context…...

Vue 3 + TypeScript 实现一个多语言国际化组件(支持语言切换与内容加载)

文章目录 一、项目背景与功能概览二、项目技术架构与依赖安装2.1 技术栈2.2 安装依赖 三、国际化组件实现3.1 创建 i18n 实例3.2 配置 i18n 到 Vue 应用3.3 在组件中使用国际化内容3.4 支持语言切换 四、支持类型安全4.1 添加类型支持4.2 自动加载语言文件 一、项目背景与功能概…...

PhalApi 2.x:让PHP接口开发从“简单”到“极简”的开源框架

—— 专为高效开发而生&#xff0c;助你轻松构建高可用API接口 一、为什么选择PhalApi 2.x&#xff1f; 1.轻量高效&#xff0c;性能卓越 PhalApi 2.x 是一款专为接口开发设计的轻量级PHP框架&#xff0c;其核心代码精简但功能强大。根据开发者实测&#xff0c;在2核2G服务器…...

库magnet使用指南

Magnet 多线程控制库使用指南 目录 库功能概述环境配置核心类与接口基础使用示例代码生成工具高级功能与改进建议完整示例代码常见问题解答 https://blink.csdn.net/details/1872803?spm1001.2014.3001.5501 1. 库功能概述 Magnet 库提供以下核心功能&#xff1a; 多线程…...

Oracle数据库数据编程SQL<9.3 数据库逻辑备份和迁移Data Pump (EXPDP/IMPDP) 导出、导入补充>

Oracle Data Pump 是 Oracle 10g 引入的高效数据迁移工具,相比传统的 EXP/IMP 工具,它提供了更强大的功能和显著的性能提升。以下是对 EXPDP 和 IMPDP 工具的全面讲解。 目录 一、高级功能扩展 1. 数据过滤与转换 2. 加密与安全 二、性能调优进阶 1. 并行处理优化 2. …...