首页 > 其他分享 >ThreadLocal详解

ThreadLocal详解

时间:2024-06-22 22:28:53浏览次数:11  
标签:变量 ThreadLocalMap threadLocal ThreadLocal 详解 线程 key

在做项目时发现项目中一般都会把用户信息存入ThreadLocal中,方便后续使用用户信息。但是ThreadLocal的原理是什么呢?这里结合网上的资料记录一下我自己的理解。

ThreadLocal是什么?

网上有的说法是ThreadLocal是线程本地变量,如果创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程安全问题。
但是我觉得这段话说的不够清楚,甚至有歧义,至少我初看时是理解错了。
实际上这个ThreadLocal就是一个类,用来操作ThreadLocalMap的一个工具类(后面会解释为什么这么说),那这个ThreadLocalMap又是什么呢?
每个Thread线程下面都有一个成员变量threadLocals,可以看到数据类型就是ThreadLocalMap。
在这里插入图片描述
所以并不是每个线程都有一个ThreadLocal,而是每个线程都有一个ThreadLocalMap,而ThreadLocalMap根据这个名字就应该知道具体结构是一个map结构,如下图所示。
在这里插入图片描述
如果有多个用户,即多个线程,情况就是
在这里插入图片描述
可以看到对于ThreadLocalMap每个entry的key就是ThreadLocal变量本身的引用,而value为不同线程下的存入的数据。
并且,可以看出来,不同的线程中有不同的ThreadLocalMap,但是entry中key指向ThreadLocal是同一个,也就是说ThreadLocal是被不同的线程共享的,或许这就是文章开头那段概念中“访问这个变量的每个线程都会有这个变量的一个本地拷贝”的意思?

ThreadLocal如何保证线程隔离?

线程隔离就是指存在这个线程的数据不能被其它线程改变。
以存取用户信息为例子。

  • 创建一个ThreadLocal变量
private static final ThreadLocal<User> threadLocal = new ThreadLocal<>();
  • 存数据。
threadLocal.set(user);

set的具体实现其实是先得到此线程的ThreadLocalMap,然后以threadLocal自身引用为key,user为value,存进ThreadLocalMap。代码如下。
在这里插入图片描述

  • 取数据
threadLocal.get();

get的具体实现也是先获得当前线程的ThreadLocalMap,然后以threadLocal自身引用为key,去ThreadLocalMap中找对应的value。(谁调用的get()谁就是key)
在这里插入图片描述

  • 因为不同线程拥有不同的ThreadLocalMap,所以不同线程的存取数据操作都是在不同的空间的进行的,互不影响。达到线程隔离的效果。其实也就是每个线程开辟了一个自己的独立空间(ThreadLocalMap)存数据,虽然开启空间的钥匙是一样的(ThreadLocal),但是你没办法拿这个钥匙开启我的空间,因为你根本看不到我的空间,没有访问我的空间的机会。
  • 可以看出来,threadLocal.set(),threadLocal.get()其实都在对ThreadLocalMap进行读写,所以前面我才说ThreadLocal就像是一个用来操作ThreadLocalMap的工具类。
    在这里插入图片描述

ThreadLocal内存泄漏问题

这里要注意的一点是,ThreadLocalMap中entry的key,也就是ThreadLocal变量本身的引用是一个弱引用。
在这里插入图片描述
而弱引用只要垃圾回收机制一运行,不管JVM的内存空间是否充足,都会回收该对象占用的内存。因此ThreadLocalMap中的key很容易被回收了,key为null,而这时候整个ThreadLocalMap还在,因为ThreadLocalMap生命周期是和Thread一样的。key没了,value还在,这就造成了内存泄露
而解决这个问题的办法就是使用完ThreadLocal后,手动调用remove()方法释放内存空间。

标签:变量,ThreadLocalMap,threadLocal,ThreadLocal,详解,线程,key
From: https://blog.csdn.net/Black_cat_look/article/details/139887265

相关文章

  • FastJson使用详解
    FastJson文章目录第一章FastJson使用详解这一篇就够了第二章FastJsonHttpMessageConverter类的作用与使用详解第三章Jackson使用详解文章目录FastJson文章目录前言一、FastJson是什么?二、使用步骤1.引入库2.序列化和反序列化Java对象3解析JSON字符串4使用注解......
  • 【python】pandas:Series详解
    Series是Pandas库中的一个核心数据结构,用于处理一维数组型数据,并带有与之相关的数据标签(通常称为“索引”)。Series可以被视为一个固定大小的、有序的、可以包含任何数据类型的数组。以下是关于Series的详细介绍:定义Series是一个一维的、大小可变的、可以包含任何数据类型......
  • 十大经典排序算法——插入排序与希尔排序(超详解)
    一、插入排序1.基本思想直接插入排序是一种简单的插入排序法,基本思想是:把待排序的记录按其数值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。2.直接插入排序当插入第end+1 个元素时,前面的arr[0],arr[1],... ,arr[end]已经......
  • 嵌入式秋招面试中,一定要掌握的嵌入式c基础——关键字详解(1)
    哈喽,大家好,这里是自律鸽。正如标题所强调的,在嵌入式秋招面试中,被问到c语言相关知识的概率几乎达到了百分之百。我本人也在去年的秋招中深切体验了这一点。因此,我想与大家分享一些面试中常问的嵌入式c基础,这些也都是我在求职过程中积累的宝贵经验。关键字1、sizeof:经常被问到......
  • 详解 ClickHouse 的分片集群
    一、简介分片功能依赖于Distributed表引擎,Distributed表引擎本身不存储数据,有点类似于MyCat之于MySql,成为一种中间件,通过分布式逻辑表来写入、分发、路由来操作多台节点不同分片的分布式数据ClickHouse进行分片集群的目的是解决数据的横向扩容,通过分片把一份完整......
  • 掌握ChatGPT:提示工程入门详解
    随着人工智能的发展,提示工程成为了使用ChatGPT等语言模型的核心技术。对于初学者,理解和运用提示工程是提高与ChatGPT互动效果的关键。什么是提示工程?提示工程是通过设计和优化输入文本(提示)来引导AI生成特定输出的过程。它包括思路链(Chain-of-Thought)、提示链接(PromptChain......
  • MySQL-文件排序原理详解
    目录Usingfilesort文件排序原理详解filesort文件排序方式示例验证下各种排序方式:单路排序的详细过程:双路排序的详细过程:单路排序相对于双路排序具有以下特点:Usingfilesort文件排序原理详解filesort文件排序方式单路排序:是一次性取出满足条件行的所有字段,然后在s......
  • DCF协议详解
    1概述DCF机制是IEEE802.11标准的核心接入机制,网络中所有节点都应该具备该功能。DCF主要采用带有冲突避免的载波侦听多路访问(CarrierSenseMultipleAccessCollisionAvoidance,CSMA/CA)协议,当使用CSMA时,一个想要发送数据的站点首先侦听传输煤质一段定长时间,如果......
  • [MySQL总结] Explain详解、索引最佳优化
    目录ExplainExplain分析示例explain两个变种explain中的列1.id列2.select_type列3.table列4.type列5.possible_keys列6.key列7.key_len列8.ref列9.rows列10.Extra列索引最佳优化实践1.全值匹配2.最左前缀法则3.不在索引列上做任何操作(计算、函数、(自动or......
  • MySQL总结-索引优化实战详解一
    目录一、索引下推优化详解1.联合索引第一个字段用范围不会走索引2.强制走索引3.覆盖索引优化4.in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描5.likeKK%一般情况都会走索引索引下推(IndexConditionPushdown,ICP)为什么范围查找Mysql没有......