深入解读 ThreadLocal 源码及其在 ThreadLocalContext 中的使用

深入解读 ThreadLocal 源码及其在 ThreadLocalContext 中的使用

ThreadLocal 是 Java 中用于提供线程局部变量的一种机制,通过为每个线程提供独立的变量副本,保证了线程之间的数据隔离性。本文将深入解读 ThreadLocal 的源码,并展示其在 ThreadLocalContext 中的实际应用。

一、ThreadLocal 源码解读

1.1 ThreadLocal 类的定义

ThreadLocal 类位于 java.lang 包中,以下是其简化的定义:

public class ThreadLocal<T> {// 构造方法public ThreadLocal() {}// 初始化方法,提供初始值protected T initialValue() {return null;}// 获取当前线程的值public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T) e.value;return result;}}return setInitialValue();}// 设置当前线程的值public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}// 移除当前线程的值public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);}// 其他内部方法省略...
}

1.2 ThreadLocalMap 内部类

ThreadLocal 的核心是一个内部类 ThreadLocalMap,它是一个自定义的哈希表,用于存储每个线程的局部变量。

static class ThreadLocalMap {static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}private Entry[] table;private int size = 0;// 其他内部方法省略...
}

1.3 ThreadLocal 的工作原理

  • 每个线程持有一个 ThreadLocalMap:每个线程在其内部维护一个 ThreadLocalMap 实例,用于存储该线程的所有 ThreadLocal 变量及其对应的值。
  • 弱引用键ThreadLocalMap 使用 ThreadLocal 变量作为键,并以弱引用的形式存在,防止内存泄漏。
  • 隔离性:每个线程都有独立的 ThreadLocalMap,从而保证了线程之间的数据隔离。

二、ThreadLocal 在 ThreadLocalContext 中的使用

ThreadLocalContext 是一个典型的使用 ThreadLocal 提供线程局部变量的场景,通常用于存储线程相关的上下文信息,例如用户会话、事务管理等。

2.1 ThreadLocalContext 示例

以下是一个 ThreadLocalContext 的示例代码:

public class ThreadLocalContext {// 定义一个静态的 ThreadLocal 变量private static ThreadLocal<Map<String, Object>> threadLocal = ThreadLocal.withInitial(HashMap::new);// 获取上下文信息public static Object get(String key) {return threadLocal.get().get(key);}// 设置上下文信息public static void set(String key, Object value) {threadLocal.get().put(key, value);}// 移除上下文信息中的某个键值对public static void remove(String key) {threadLocal.get().remove(key);}// 清除当前线程的上下文信息public static void clear() {threadLocal.remove();}public static void main(String[] args) {// 创建两个线程,验证它们的 ThreadLocal 数据是否隔离Thread thread1 = new Thread(() -> {ThreadLocalContext.set("username", "Alice");System.out.println(Thread.currentThread().getName() + " username: " + ThreadLocalContext.get("username"));ThreadLocalContext.clear();});Thread thread2 = new Thread(() -> {ThreadLocalContext.set("username", "Bob");System.out.println(Thread.currentThread().getName() + " username: " + ThreadLocalContext.get("username"));ThreadLocalContext.clear();});thread1.start();thread2.start();}
}

2.2 运行结果

Thread-0 username: Alice
Thread-1 username: Bob

从运行结果可以看出,不同线程的 ThreadLocal 数据是隔离的,互不干扰。

2.3 代码分析

  • 初始化 ThreadLocal 变量

    private static ThreadLocal<Map<String, Object>> threadLocal = ThreadLocal.withInitial(HashMap::new);
    

    使用 ThreadLocal.withInitial 方法初始化线程局部变量,每个线程都会得到一个独立的 HashMap 实例。

  • 获取和设置上下文信息
    ThreadLocalContext 提供了静态方法 getset 用于获取和设置当前线程的上下文信息。

  • 清理上下文信息
    clear 方法用于在任务结束后清理当前线程的上下文信息,防止内存泄漏。

2.4 注意事项

  1. 资源清理:使用完 ThreadLocal 变量后,务必调用 remove 方法清理资源,特别是在使用线程池时。
  2. 线程隔离ThreadLocal 变量保证了线程间的数据隔离,因此适用于存储每个线程独立实例的数据,如用户会话、事务信息等。

三、总结

通过本文的介绍,我们深入解读了 ThreadLocal 的源码,了解了其工作原理,并展示了 ThreadLocalThreadLocalContext 中的实际应用。ThreadLocal 是处理多线程并发问题的有力工具,通过为每个线程提供独立的变量副本,有效保证了线程间的数据隔离,提高了程序的并发性能和稳定性。

希望本文对你理解 ThreadLocal 的工作机制和实际应用有所帮助。如果你在实际开发中需要处理线程局部变量,不妨考虑使用 ThreadLocal 提供的便捷机制。


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

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

相关文章

以数治税时代来临,企业如何应对?

全电发票是数字经济时代发票的新形态&#xff0c;顺应了数字经济潮流。现如今&#xff0c;国家正全力推动行业数字化进程&#xff0c;预计&#xff0c;2025年将基本实现发票全领域、全环节、全要素电子化&#xff0c;实现税务执法、服务、监管与大数据智能化应用深度融合、高效…

Spring事务的源码底层实现

文章目录 事务理论执行过程EnableTransactionManagement底层实现 事务 在线流程图 理论执行过程 通过事务管理器创建一个连接对象connection1设置事务隔离级别、是否只读等conn1.autocommit(false)将conn1存入ThreadLocal中Map<DataSource,Connection>执行目标方法、多…

Session会话与请求域的区别

session会话和请求域&#xff08;也称为request域&#xff09;都是用于存储和管理用户特定信息的重要概念&#xff0c;但它们在作用范围和生命周期上有显著的不同。 请求域 (Request Domain) 作用范围&#xff1a;请求域是面向单次请求的。每次HTTP请求都会创建一个新的request…

Java中的程序异常处理介绍

一、异常处理机制 Java提供了更加优秀的解决办法&#xff1a;异常处理机制。 异常处理机制能让程序在异常发生时&#xff0c;按照代码的预先设定的异常处理逻辑&#xff0c;针对性地处理异常&#xff0c;让程序尽最大可能恢复正常并继续执行&#xff0c;且保持代码的清晰。 Ja…

算法刷题日志 —— 数组和位运算

文章目录 [461. 汉明距离](https://leetcode.cn/problems/hamming-distance/submissions/542447020/)[448. 找到所有数组中消失的数字](https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/submissions/)[136. 只出现一次的数字](https://leetcode.cn/pro…

最长回文串

描述&#xff1a; 最长回文串 思路&#xff1a; 统计每个字母出现次数&#xff0c;如果是偶数&#xff0c;ret x;如果是存在奇数的话&#xff0c;就可以放在中间&#xff0c;ret 1. 代码&#xff1a; class Solution { public:int hash[200];int longestPalindrome(str…

记一次rocketMq根据配置文件读取listener consumerGroup异常

记一次rocketMq根据配置文件读取listener consumerGroup异常 引现象处理 引 rocketMq通常需要配置topic和consumerGroup&#xff0c;而这两个参数往往是不会直接定值写死&#xff0c;而是通过application配置文件配置变量的方式来注入。 现象 今天新增了几个topic和consumer…

AI智能修复视频,垃圾画质也变高清 HD——牛小影

很多时候&#xff0c;从网上下载的视频或监控视频都是模糊的。有什么方法或者软件可以让哪些模糊的视频恢复清晰吗&#xff1f;今天就给大家推荐一个可以使模糊的视频变清晰的软件。 我们都知道用PS或者一些修复工具可以修复模糊的图片&#xff0c;但是很多人不知道的是视频也可…

构建LangChain应用程序的示例代码:46、使用 Meta-Prompt 构建自我改进代理的 LangChain 实现

Meta-Prompt 实现 摘要&#xff1a; 本文介绍了 Noah Goodman 提出的 Meta-Prompt 方法的 LangChain 实现&#xff0c;该方法用于构建能够自我反思和改进的智能代理。 核心思想&#xff1a; Meta-Prompt 的核心思想是促使代理反思自己的性能&#xff0c;并修改自己的指令。…

上班族要怎么挑选智能猫砂盆?今年最受欢迎的牌子都在这里了!

对于上班族来说&#xff0c;猫砂盆里的猫屎到底该如何是好&#xff0c;放到下班回来再铲&#xff0c;猫砂的臭味早就飘满屋子&#xff0c;想立刻铲掉吧&#xff0c;班不要上啦&#xff1f;可是不铲就会生细菌&#xff0c;谁也不想花个几千块去给猫咪看病吧&#xff0c;谁不希望…

运算逻辑符的短路特性

在开发时遇到了这样一个问题&#xff1a; public boolean isPasswordNullOrEmpty(Context context) {return getPassword(context) ! null && !getPassword(context).isEmpty; } 这个方法想要实现的效果是获取一个password是否为空的状态&#xff0c;但会出现报错&am…

Linux:进程和计划任务管理

目录 一、程序和进程 1.1、程序 1.2、进程 1.3、线程 1.4、协程 二、查看进程相关命令 2.1、ps命令&#xff08;查看静态的进程统计信息&#xff09; 第一行为列表标题&#xff0c;其中各字段的含义描述如下 2.2、top命令&#xff08;查看进程动态信息&#xff09; 2…

商城积分系统的设计方案(上)-- 需求分析

一、背景 用户在参与公司的促销活动&#xff0c;比如邀请用户下单支付&#xff0c;可以获得虚拟货币。它可以用于解锁学习课程。 商品在定价的时候&#xff0c;需支持虚拟货币&#xff0c;用户在购买该商品的时候&#xff0c;可使用虚拟货币进行支付。 在电商体系中&#xf…

等保2.0自查表,扩展部分

等保2.0自查表&#xff0c;扩展部分&#xff0c;参考标准&#xff1a; GB∕T 22239-2019 《信息安全技术 网络安全等级保护基本要求》 GB∕T 28448-2019 《信息安全技术网络安全等级保护测评要求》 云计算安全 层面 控制点 检查项 三级要求 二级要求 安全物理环境 基础…

android:exported=“false“

书籍&#xff1a; 《第一行代码 Android》第三版 开发环境&#xff1a; Android Studio Jellyfish | 2023.3.1 问题&#xff1a; A launchable activity must be exported as of Android 12, which also makes it available to other apps 新建的activity中的android:exp…

PID算法介绍以及代码实现过程说明

写在正文之前 在上一篇文章就说会在这两天会基于PID写一个文章&#xff0c;这里的原理部分值得大家都看一下&#xff0c;代码部分的实现是基于python的&#xff0c;但是对于使用其他编程语言的朋友&#xff0c;由于我写的很通俗易懂&#xff0c;所以也值得借鉴。 一、PID算法…

最大流的学习代码,匹配问题的学习 使用c++

使用一个例子学习最大流和匹配问题&#xff0c;假如某地有n个出租车司机和m个正在打车的乘客&#xff0c;他们应该如何匹配&#xff1b; #include <iostream> // 用于输入输出 #include <vector> // 用于动态数组 #include <queue> // 用于广度优先…

linux基于wifi,Xshell的远程连接

最近有个比赛&#xff0c;要使用ros小车但是系统是ubuntu20.04无桌面系统刚开始接触linux的我啥都不会&#xff0c;就一个简单的连接wifi都搞了3天才搞通。再此进行一个总结。参考博客原文链接&#xff1a;https://blog.csdn.net/qq_51491920/article/details/126221940 一、什…

短说V4.1.5及PC端V3.1.4正式版发布公告

Hi 大家好&#xff0c; 我是给你们带来惊喜的运营小番茄。 本期更新为短说 4.1.5和PC端3.1.4的正式版。 本次修复上个版本中的问题和功能优化&#xff0c;以及新增了如下功能&#xff1a; PC端支持发布秀米帖&#xff0c;可支持部分秀米格式&#xff1b;后台管理类消息新增…

C#中的容器

1、数组 数组是存储相同类型元素的固定大小的顺序集合 声明数组时&#xff0c;必须指定数组的大小 2.数组的插入和删除数据比较麻烦&#xff0c;但是查询比较快 2、动态数组&#xff08;ArrayList&#xff09; 动态数组&#xff1a;可自动调节数组的大小 可以存储任意类型数…