ThreadLocal基本介绍
文章目录
- 什么是ThreadLocal
- ThreadLocal解决了什么问题
- ThreadLocal的作用
- ThreadLocal的使用场景
- ThreadLocal的代码示例
- ThreadLocal的优点
- ThreadLocal的缺点
- 与volatile、synchronized、ThreadLocal比较
- 总结
什么是ThreadLocal
ThreadLocal是Java中的一个线程本地变量,它提供了一种在多线程环境下保持变量的副本,每个线程都可以独立地修改自己的副本,而不会影响其他线程的副本。
ThreadLocal解决了什么问题
在多线程环境下,共享变量的访问可能会引发线程安全问题。例如,多个线程同时访问同一个变量时,可能会导致数据的不一致性和竞态条件。ThreadLocal提供了一种解决方案,通过为每个线程提供独立的副本,避免了共享变量的竞争和同步问题,从而解决了线程安全问题。
ThreadLocal的作用
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
作者:安仔夏天勤奋
链接:https://www.jianshu.com/p/6fc3bba12f38
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
ThreadLocal的使用场景
ThreadLocal适用于以下场景:
数据库连接管理:每个线程需要独立的数据库连接,可以使用ThreadLocal来管理每个线程的连接。
用户身份认证:每个线程需要独立的用户身份信息,可以使用ThreadLocal来存储用户的身份信息。
线程上下文传递:多个方法之间需要共享一些上下文信息,可以使用ThreadLocal来传递上下文信息。
ThreadLocal的代码示例
下面是一个使用ThreadLocal的简单示例,用于存储用户的身份信息:
public class UserContext {private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();public static void setUser(User user) {userThreadLocal.set(user);}public static User getUser() {return userThreadLocal.get();}public static void clearUser() {userThreadLocal.remove();}
}public class User {private String name;// ... 其他属性和方法
}public class Main {public static void main(String[] args) {User user1 = new User("Alice");User user2 = new User("Bob");UserContext.setUser(user1);System.out.println(UserContext.getUser().getName()); // 输出:AliceUserContext.setUser(user2);System.out.println(UserContext.getUser().getName()); // 输出:BobUserContext.clearUser();System.out.println(UserContext.getUser()); // 输出:null}
}
在上面的示例中,UserContext类使用ThreadLocal来存储用户的身份信息。通过调用setUser方法来设置当前线程的用户信息,调用getUser方法来获取当前线程的用户信息,调用clearUser方法来清除当前线程的用户信息。
ThreadLocal的优点
线程隔离:每个线程都有自己独立的变量副本,不会受其他线程的影响,实现了线程间的隔离。
简单易用:使用ThreadLocal非常简单,只需要创建一个ThreadLocal对象,并调用其get和set方法即可。
高效性:ThreadLocal使用了线程的ThreadLocalMap来存储变量副本,访问速度快。
ThreadLocal的缺点
内存泄漏:如果ThreadLocal变量没有及时清理,可能会导致内存泄漏。因为ThreadLocalMap中的Entry会持有ThreadLocal对象的强引用,如果ThreadLocal对象没有被及时回收,就会造成内存泄漏。
线程间数据共享困难:ThreadLocal只能在当前线程内共享数据,在线程间传递数据相对困难,需要借助其他方式(如参数传递)来实现。
与volatile、synchronized、ThreadLocal比较
在简单变量读写场景中,使用volatile关键字可以保证变量的可见性和禁止指令重排序,但不涉及锁竞争。
在复杂的线程同步和互斥场景,synchronized关键字提供了安全且经过测试的机制来实现线程间的互斥。但需要注意锁的竞争和上下文切换会带来性能开销。
ThreadLocal提供了一种简单的方式来实现线程间的变量隔离和线程上下文传递。它通过为每个线程提供独立的变量副本,避免了锁竞争,并且不涉及上下文切换,访问速度较快。但需要注意及时清理ThreadLocal变量,避免内存泄漏。
综上所述,选择合适的机制取决于具体的使用场景。对于简单的变量读写场景,可以使用volatile关键字。对于复杂的线程同步和互斥场景,synchronized提供了可靠的机制。而ThreadLocal则特别适用于需要变量隔离和线程上下文传递的场景,可以提供简单且高效的解决方案。
总结
在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。 初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。 然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。
实际的通过ThreadLocal创建的副本是存储在每个线程自己的threadLocals中的;
为何threadLocals的类型ThreadLocalMap的键值为ThreadLocal对象,因为每个线程中可有多个threadLocal变量,就像上面代码中的longLocal和stringLocal;
在进行get之前,必须先set,否则会报空指针异常;如果想在get之前不需要调用set就能正常访问的话,必须重写initialValue()方法。 因为在上面的代码分析过程中,我们发现如果没有先set的话,即在map中查找不到对应的存储,则会通过调用setInitialValue方法返回i,而在setInitialValue方法中,有一个语句是T value = initialValue(), 而默认情况下,initialValue方法返回的是null。
相关文章:

ThreadLocal基本介绍
文章目录 什么是ThreadLocalThreadLocal解决了什么问题ThreadLocal的作用 ThreadLocal的使用场景ThreadLocal的代码示例ThreadLocal的优点ThreadLocal的缺点与volatile、synchronized、ThreadLocal比较 总结 什么是ThreadLocal ThreadLocal是Java中的一个线程本地变量…...

ffmpeg源码编译成功,但是引用生成的静态库(.a)报错,报错位置在xxx_list.c,报错信息为某变量未定义
背景:本文是对上一个文章的补充,在源码编译之前,项目是有完整的ffmpeg编译脚本的,只不过新增了断点调试ffmpeg,所以产生的上面的文章,也就是说,我在用make编译成功后,再去做的源码编…...

2023爱分析·信创云市场厂商评估报告:中国电子云
01 研究范围定义 信创2.0时代开启,信创进程正在从局部到全面、从细分到所有领域延展。在这个过程中,传统的系统集成,也在逐步向信创化、数字化及智能化转变。随着信创产业的发展,企业需要更多的技术支持和服务,而传统的系统集成已…...
网络安全学习笔记——XFF攻击流程
手工注入 手动报错注入,填写格式如:X-Forwarded-For: and updatexml(1,concat(0x7e,(select database()),0x7e),1) or 11 库名 1 and updatexml(1,concat(0x7e,database(),0x7e),1), 表名 1 and updatexml(1,concat(0x7e,(select table_name from…...
微信小程序阻止用户返回上一页,并弹窗给用户确定是否要返回上一页
在onload中调用微信的enableAlertBeforeUnload方法,在首次进入会自动监听当前的页面,在返回的时候会自动弹出弹窗阻止用户返回上一页,点击确定则返回上一页,取消则停留在当前页 onLoad: function(){wx.enableAlertBeforeUnload({…...

LangChain+ChatGLM整合LLaMa模型(二)
开源大模型语言LLaMa LLaMa模型GitHub地址添加LLaMa模型配置启用LLaMa模型 LangChainChatGLM大模型应用落地实践(一) LLaMa模型GitHub地址 git lfs clone https://huggingface.co/huggyllama/llama-7b添加LLaMa模型配置 在Langchain-ChatGLM/configs/m…...

【NLP】训练chatglm2的评价指标BLEU,ROUGE
当进行一定程度的微调后,要评价模型输出的语句的准确性。由于衡量的对象是一个个的自然语言文本,所以通常会选择自然语言处理领域的相关评价指标。这些指标原先都是用来度量机器翻译结果质量的,并且被证明可以很好的反映待评测语句的准确性&a…...

java+springboot+mysql员工工资管理系统
项目介绍: 使用javaspringbootmysql开发的员工工资管理系统,系统包含超级管理员,系统管理员、员工角色,功能如下: 超级管理员:管理员管理;部门管理;员工管理;奖惩管理&…...

FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版
FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版是一个完整的软件音乐制作环境或数字音频工作站(DAW)。它代表了 25 多年的创新发展,将您创作、编曲、录…...

探索Python数据容器之乐趣:列表与元组的奇妙旅程!
文章目录 零 数据容器入门一 数据容器:list(列表)1.1 列表的定义1.2 列表的下表索引1.3 列表的常用操作1.3.1 列表的查询功能1.3.2 列表的修改功能1.3.3 列表常用方法总结 1.4 补充:append与extend对比1.5 list(列表)的遍历1.6 补…...

Python自动化实战之使用Pytest进行API测试详解
概要 每次手动测试API都需要重复输入相同的数据,而且还需要跑多个测试用例,十分繁琐和无聊。那么,有没有一种方法可以让你更高效地测试API呢?Pytest自动化测试!今天,小编将向你介绍如何使用Pytest进行API自…...

TCP的三次握手以及四次断开
TCP的三次握手和四次断开,就是TCP通信建立连接以及断开的过程 目录 【1】TCP的三次握手过程 ---- TCP建立连接的过程 【2】TCP的四次挥手 ---- TCP会话的断开 注意: 【1】TCP的三次握手过程 ---- TCP建立连接的过程 三次握手的过程:…...
目标检测YOLO实战应用案例100讲-基于视觉与激光雷达信息融合的智能车辆目标检测研究
目录 前言 传感器选型及同步 2.1 各传感器工作原理及性能对比 2.1.1 视觉传感器...
Day 22 C++ STL常用容器——string容器
string容器 概念本质string和char 区别:特点string构造函数构造函数原型 string赋值操作赋值的函数原型示例 string字符串拼接函数原型:示例 string查找和替换函数原型示例 string字符串比较比较方式 字符串比较是按字符的ASCII码进行对比函数原型示例 s…...

使用Socket实现UDP版的回显服务器
文章目录 1. Socket简介2. DatagramSocket3. DatagramPacket4. InetSocketAddress5. 实现UDP版的回显服务器 1. Socket简介 Socket(Java套接字)是Java编程语言提供的一组类和接口,用于实现网络通信。它基于Socket编程接口,提供了…...

【MCU学习】GD32F427VG开发
(一)学习文档和例程 兆易创新GD32 MCU参考资料下载 1.GD232F4xx的Keil芯片支持包 2.标准固件库和示例程序 3.GD32F4xx_固件库使用指南_Rev1.2 4.用户手册:GD32F4xx_User_Manual_Rev2.8_CN 5.数据手册:GD32F427xx_Datasheet_Rev…...

Acwing.877 扩展欧几里得算法
题目 给定n对正整数ai , bi,对于每对数,求出一组ai ,g,使其满足ai* xi bi * yi gcd(ai ,bi)。 输入格式 第一行包含整数n。 接下来n行,每行包含两个整数ai , bi。 输出格式 输出共n行,对于每组ai, bi,…...

基于自组织竞争网络的患者癌症发病预测(matlab代码)
1.案例背景 1.1自组织竞争网络概述 前面案例中讲述的都是在训练过程中采用有导师监督学习方式的神经网络模型。这种学习方式在训练过程中,需要预先给网络提供期望输出,根据期望输出来调整网络的权重,使得实际输出和期望输出尽可能地接近。但是在很多情况下,在人们认知的过程中…...
golang mongodb
看代码吧 package main// 链接案例 https://www.mongodb.com/docs/drivers/go/current/fundamentals/connection/#connection-example // 快速入门 https://www.mongodb.com/docs/drivers/go/current/quick-start/ import ("context""fmt""log"…...

docker中的jenkins去配置sonarQube
docker中的jenkins去配置sonarQube 1、拉取sonarQube macdeMacBook-Pro:~ mac$ docker pull sonarqube:8.9.6-community 8.9.6-community: Pulling from library/sonarqube 8572bc8fb8a3: Pull complete 702f1610d53e: Pull complete 8c951e69c28d: Pull complete f95e4f8…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础
在构建任何动态、数据驱动的Web API时,一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说,深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言,以及学会如何在Python中操作数据库,是…...
CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14
什么是 Pattern Matching(模式匹配) ❝ 模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞ 你给的定义拆解: ✴ Instead of …...
Vue 实例的数据对象详解
Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...