【Java】ThreadLocal原理与使用场景
ThreadLocal原理:
字段:
//ThreadLocal对象的哈希码
private final int threadLocalHashCode = nextHashCode();//生成ThreadLocal对象的哈希码时,需要用到该对象,从0开始
private static AtomicInteger nextHashCode =new AtomicInteger();//哈希码的增长值
private static final int HASH_INCREMENT = 0x61c88647;
nextHashCode()方法:
private static int nextHashCode() {//通过AtomicInteger对象生成ThreadLocal对象的哈希码并返回//步长为:HASH_INCREMENTreturn nextHashCode.getAndAdd(HASH_INCREMENT);}
方法实现:
(1)get()方法:
public T get() {//获取当前线程Thread t = Thread.currentThread();//获取当前线程的ThreadLocalMap对象ThreadLocalMap map = getMap(t);//判断ThreadLocalMap对象是否为空//map不为null说明有键值对if (map != null) {//在map中,ThreadLocal作为keyThreadLocalMap.Entry e = map.getEntry(this);//如果key不为空if (e != null) {@SuppressWarnings("unchecked")//通过key获取值并返回T result = (T)e.value;return result;}}//如果map为null,则创建map//当前ThreadLocal对象作为key,null作为value存入map中//返回nullreturn setInitialValue();}
(2)set()方法:
public void set(T value) {//获取当前线程的ThreadLocalMap对象Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);//如果map不为nullif (map != null)//将当前ThreadLocal作为key//参数value作为值,存入ThreadLocalMap中map.set(this, value);else//map为null,则创建map//将当前ThreadLocal对象作为firstKey,参数value作为firstValuecreateMap(t, value);}
通过set方法,我们可以知道:
1、线程调用ThreadLocal对象的set方法时,会获取当前线程的ThreadLocalMap对象。
2、随后会将当前ThreadLocal对象作为key,参数value作为值存储到线程内部的ThreadLocalMap对象中。
3、这意味着即使ThreadLocal是多个线程共享的变量也不会存在线程安全问题,因为每个线程都只在操作自己的ThreadLocalMap,ThreadLocal只是作为key保存在map中。
(3)remove()方法:
public void remove() {//获取当前线程的ThreadLocalMap对象ThreadLocalMap m = getMap(Thread.currentThread());//如果map不为nullif (m != null)//将当前ThreadLocal对象从ThreadLocalMap中移除m.remove(this);}
ThreadLocalMap、ThreadLocal、Thread三者之间的联系:

测试:
(1)User类:
package test;public class User {private Integer id;private String name;public User(Integer id, String name) {this.id = id;this.name = name;}public User(){}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}
(2)UserHolder类:
package test;public class UserHolder {private static final ThreadLocal<User> threadLocal = new ThreadLocal<>();public static void set(User user){threadLocal.set(user);}public static User get(){User user = threadLocal.get();return user;}
}
ThreadLocal作为静态字段存在于UserHolder类中,UserHolder的set方法、get方法实际上都是由ThreadLocal实现,这里使用到了组合的思想。
(3)ThreadLocalTest类:
package test;public class ThreadLocalTest {public static void main(String[] args) throws InterruptedException {new Thread(() -> {System.out.println("Thread-1线程运行,存储User对象到TheadLocal中...");createAndHold(1,"张三");User user = UserHolder.get();System.out.println(user);}, "Thread-1").start();System.out.println("main线程阻塞...");Thread.sleep(3000);System.out.println("main线程运行,获取UserHolder存储的User对象...");User user = UserHolder.get();System.out.println("user对象:" + user);}private static void createAndHold(Integer id,String name){User user = new User(id, name);UserHolder.set(user);}
}
代码解读:
1、main线程一开始会阻塞3s,Thread-1线程运行,将User对象存入ThreadLocal并打印。
2、main线程解除阻塞后,会去获取ThreadLocal中存储的User对象;照理来说,ThreadLocal对象是静态成员,对于两个线程来说是共享变量,此时main线程应该会获取到Thread-1存入的User对象。
3、但我们知道,ThreadLocal真正操作的是每个线程内部的ThreadLocalMap,ThreadLocal对象只作为key存储到每个线程自己的ThreadLocalMap中,我们可以通过key找到value,实现线程间的隔离。
测试结果:

ThreadLocal使用场景:
(1)多线程隔离: 多个线程使用ThreadLocal访问共享变量,每个线程都会得到共享变量的一个副本,后续多个线程自己所属副本的所有操作不会冲突,没有线程安全问题。
(2)线程内共享:ThreadLocal 可以用于在整个线程生命周期内共享这些上下文信息,而不需要显式地传递参数。
(3)存储用户信息:在Web应用中,可能会在用户登录后将用户身份信息存储在 ThreadLocal 中,以便在整个请求处理过程中方便地访问用户信息,而不必在每个方法中都传递用户信息参数。
相关文章:
【Java】ThreadLocal原理与使用场景
ThreadLocal原理: 字段: //ThreadLocal对象的哈希码 private final int threadLocalHashCode nextHashCode();//生成ThreadLocal对象的哈希码时,需要用到该对象,从0开始 private static AtomicInteger nextHashCode new Atomic…...
软件测试/测试开发丨Linux进阶命令(curl、jq)
1、 curl 接口请求 curl是一个发起请求数据给服务器的工具curl支持的协议FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSPcurl是一个非交互的工具 2、 curl 发起 get 请求 -G:使用get请求-d…...
模式识别与机器学习-SVM(带软间隔的支持向量机)
SVM(带软间隔的支持向量机) 软间隔思想的由来软间隔的引入 谨以此博客作为复习期间的记录。 软间隔思想的由来 在上一篇博客中,回顾了线性可分的支持向量机,但在实际情况中,很少有完全线性可分的情况,大部分线性可分…...
CentOS 7 firewalld+ipset+定时任务防御ssh暴力破解——筑梦之路
对于暴露在公网上的linux服务器,很容易被暴力破解登陆,为了增强服务器的安全性,因此对于ssh安全加固是很有必要的,这里主要介绍centos7 系统如何使用ipsetfirewalld定时任务来对ssh服务进行安全加固。 定义firewalld ipset fire…...
ElasticSearch的RestClient结合Sniffer提高可用性
一、背景 由于要安装分词器插件,所以需要重启ElasticSearch集群以使得新安装的插件生效 但是在重启集群的过程中,服务端代码却出现了大量错误,如下所示 java.net.ConnectException: Connection refused at org.elasticsearch.client.R…...
【网络面试(2)】DNS原理-域名和IP地址的查询转换
从上一篇博客我们得知浏览器是如何生成了HTTP消息了,但是浏览器作为应用程序,是不具备向网络中发送请求的能力,而是需要委托给操作系统的内核协议栈来发送请求。在委托协议栈之前,浏览器还要做的一件事情就是将域名转换为IP地址。…...
【PHP】函数array_intersect、array_diff:从数组中取出、去除指定的几个键值
1.从数组中取出 :array_intersect 要从数组中取出指定的几个键值,可以使用 array_intersect_key 函数。以下是一个示例: $array [name > John,age > 30,email > johnexample.com,city > New York ];$keys [name, email];$resu…...
【华为机试】2023年真题B卷(python)-冠亚军排名-奖牌榜排名
一、题目 题目描述: 2012伦敦奥运会即将到来,大家都非常关注奖牌榜的情况,现在我们假设奖牌榜的排名规则如下. 1.首先gold medal数量多的排在前面 2.其次silver medal数量多的排在前面 3.然后bronze medal数量多的排在前面 4.若以上三个条…...
MyBatisPlus之逻辑删除
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 MyBatisPlus之逻辑删除 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是逻辑删…...
在macOS中搭建.NET MAUI开发环境
文章目录 准备安装扩展安装 .NET安装工作负载安装 Xcode 命令行工具调试安卓应用安装 JDK安装 Android SDK 安装 Android 模拟器安装模拟器安装镜像创建虚拟机 同意许可条款创建 MAUI 项目调试 MAUI 应用切换调试目标 参考资料 准备 一台 macOS Monterey 以上的电脑安装 XCode…...
[NCTF 2022]calc
[NCTF 2022]calc 考点:python环境变量注入 打开题目,F12有hint 访问一下得到源码 app.route("/calc",methods[GET]) def calc():ip request.remote_addrnum request.values.get("num")log "echo {0} {1} {2}> ./tmp/log…...
【pandas_不重复项计数】
听说WPS没有非重复项计数的功能,而office需要添加到数据模型之后,才可以使用该功能。而用pandas,既可以对重复项计数,又可以对非重复项计数。 # 使用提醒: # 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能 # 2. pack…...
菜鸟学习vue3笔记-vue hooks初体验
import { ref } from "vue"; export default function () {let a1 ref(1);let a2 ref(5);let c ref(0);function add() {a1.value;a2.value;}return {add,a1,a2,c,}; }<template><div><p>第一个数字{{ a1 }}</p><p>第二个数字{{ a2…...
81 使用DFS和BFS解机器人的运动范围
问题描述:地上有一个m行n列的方格,从坐标[0,0]到坐标[m-1,n-1].一个机器人从坐标[0,0]的格子开始移动,他每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。 public int numB…...
vue-springboot基于JavaWeb的家装一体化商城平台guptn
针对用户需求开发与设计,该技术尤其在各行业领域发挥了巨大的作用,有效地促进了家装一体化的发展。然而,由于用户量和需求量的增加,信息过载等问题暴露出来,为改善传统线下管理中的不足,本文将提出一套基于…...
.NET进阶篇06-async异步、thread多线程2
知识须要不断积累、总结和沉淀,思考和写做是成长的催化剂web 内容目录 1、线程Thread 一、生命周期 二、后台线程 三、静态方法 1.线程本地存储 2.内存栅栏 四、返回值 2、线程池ThreadPool 一、工做队列 二、工做线程和IO线程 三、和Thread区别 四、定时器 1、线…...
java 方法
方法: 什么是方法,有什么用? 方法(英语单词:method)是可以完成某个特定功能的并且可以被重复利用的代码片段。 在 C 语言中,方法被称为“函数”。在 java 中不叫函数,叫做方法。 方法…...
HarmonyOS 组件通用属性之通用事件 文档参数讲解(点击事件)
我们组件中 会有很多通用的信息和方法 那么 首先 我们看通用事件 通用事件中 最常用的就是我们的点击事件 比如说 我们之前常写的 组件.onClick(()>{//事件逻辑 })但是 我们之前 都没有用它接参数 我们可以这样 Button("跳转").onClick((ewat: ClickEvent)>…...
毕业设计之开题报告
终于轮到我来写开题报告了,呃呃呃呃呃,目前有点难产了。想做的东西是关于区块链的后端设计实现,但是因为是完全原创之前没有类似的项目能去参考,所以其实有点慌的。 框架梳理 这是我们开题报告的要求: 包括题目研究的…...
【数据结构】详细剖析线性表
顺序表与链表的比较 导言一、线性表二、线性表的存储结构三、顺序表和链表的相同点四、顺序表与链表之间的差异五、存储结构的选择六、静态顺序表的基本操作七、无头结点单链表的基本操作结语 导言 大家好,很高兴又和大家见面啦!!࿰…...
COMSOL 6.1 激光粉末床熔融气孔缺陷演化仿真:开启微观世界的探索之旅
COMSOL 6.1 激光粉末床熔融气孔缺陷演化仿真案例模型 本案例选用层流和流体传热模块,采用水平集法,考虑材料的热物性以及激光加工过程中的马兰戈尼效应、熔融金属表面张力、反冲压力、相变潜热、热对流和热辐射,建立含气孔缺陷的二维数值仿真…...
5分钟掌握:billd-desk跨平台远程控制高效解决方案
5分钟掌握:billd-desk跨平台远程控制高效解决方案 【免费下载链接】billd-desk 基于Vue3 WebRTC Nodejs Flutter搭建的远程桌面控制 项目地址: https://gitcode.com/gh_mirrors/bi/billd-desk 还在为远程办公的卡顿和限制而烦恼吗?当你急需远程…...
Layerdivider:零基础上手图像分层工具的完整指南
Layerdivider:零基础上手图像分层工具的完整指南 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 为什么自动分层总是不尽如人意?设…...
Excel VBA图像处理:如何在单元格中显示并调整图片大小
在Excel中处理图片时,VBA(Visual Basic for Applications)是一个强大的工具。今天我们将讨论如何通过VBA代码在Excel的单元格中插入并调整图片大小,以及如何解决一些常见的问题。 背景介绍 假设你有一个Excel工作表,A列从A2开始存放了几个图片文件名,如"test.jpg&…...
Windows更新修复新范式:Reset-Windows-Update-Tool的系统化解决方案
Windows更新修复新范式:Reset-Windows-Update-Tool的系统化解决方案 【免费下载链接】Reset-Windows-Update-Tool Troubleshooting Tool with Windows Updates (Developed in Dev-C). 项目地址: https://gitcode.com/gh_mirrors/re/Reset-Windows-Update-Tool …...
Qwen3-Embedding-4B入门必看:Embedding模型vs LLM生成模型的核心差异
Qwen3-Embedding-4B入门必看:Embedding模型vs LLM生成模型的核心差异 1. 引言:从关键词搜索到语义理解 你是否曾经遇到过这样的困扰:在搜索引擎中输入"苹果",结果既出现了水果苹果的信息,又出现了苹果公司…...
USB251xB集线器I²C控制库:嵌入式USB设备扩展实战指南
1. 项目概述SparkFun USB Hub Qwiic USB251x 是一款面向嵌入式原型开发与量产过渡阶段的轻量级 USB 2.0 集线器控制库,专为 SparkFun 自研的 Qwiic 兼容 USB251xB 系列 Hub 模块(SPX-18014)设计。该库并非通用 USB 协议栈,而是聚焦…...
OFA视觉问答模型惊艳效果:复杂背景中主物体识别与属性描述能力
OFA视觉问答模型惊艳效果:复杂背景中主物体识别与属性描述能力 1. 模型效果惊艳展示 OFA视觉问答模型在复杂场景中的表现令人印象深刻。这个模型能够准确识别图片中的主要物体,并详细描述其属性特征,就像有一个专业的图像分析师在为你解读图…...
Java开发者必看:Istio 1.22正式弃用Mixer后,Prometheus指标丢失、日志脱节、Tracing断链问题的90分钟极速修复方案
第一章:Java开发者必看:Istio 1.22正式弃用Mixer后,Prometheus指标丢失、日志脱节、Tracing断链问题的90分钟极速修复方案Istio 1.22 彻底移除了 Mixer 组件,导致依赖其适配器模型的遥测采集链路全面失效。Java 应用在启用 Istio …...
Vision Master OpenCV 2.0 深度评测:新增YOLOv5、语义分割等ONNX模型,实战性能提升有多大?
Vision Master OpenCV 2.0 深度评测:ONNX模型实战性能全解析 当计算机视觉开发工具开始拥抱ONNX生态,技术选型的边界正在被重新定义。Vision Master OpenCV 2.0的发布恰逢其时,它不仅将YOLOv5、语义分割等前沿模型集成到可视化流程中…...
