社交网站开发注意事项/企业建设网站公司
目录
1. ThreadLocal 的主要功能?
2. ThreadLocal 代码举例
3. ThreadLocal 源码分析
3.1 ThreadLocal 的 get 方法源码解析
3.2 ThreadLocal 的 set 方法源码解析
3.3 ThreadLocal 的 createMap 方法源码解析
3.4 ThreadLocal 的 set 方法总结
4. 为什么Entry要使用弱引用指向ThreadLocal
5. 如果将 tl 设置为 null,一定要将Map中的对应记录remove
6. 线程池中的线程使用完毕归还之前清除Map
7. ThreadLocal 广泛应用于线程池
1. ThreadLocal 的主要功能?
关于 ThreadLocal 的核心功能我大致总结了以下三点
(1)线程并发:ThreadLocal 更多应用于多线程并发的场景下;
(2)传递数据:我们可以通过 ThreadLocal 在同一个线程,不同组件中传递公共变量;
(3)线程隔离:每个线程的变量都是独立隔离的,不会互相影响;
或许有些同学听完之后会有些疑惑,我来举一个简单的场景,如下图所示,假定现在有一个线程,里面有一个变量X,最先执行a方法,a方法中调用了b方法,b方法中调用了c方法,c方法又调用了d方法,层层调用,我现在问,随着调用层次的加深,层次深得方法还能获取这个变量X吗?
答案是不一定。
有些同学可能会说,我把这个参数每一层方法都传递一次不就可以了吗?这还真不一定行,如果中间你的方法调用了某些第三方库,或者做了一些别的业务逻辑,变量X就不一定能继续传递下去了;
还有的同学会说,这个简单,我把变量X设置为 static 静态的不就行了吗,所有人共享,一下子就获取到了。哎,这个也不行哦,因为我现在只是举了一个线程,如果这个变量X是一个共享资源,会有多个线程会操作它,此时它就是线程不安全的,所以设置为 static 也是不行的。
既然如此,那该怎么做呢?
这里就要用到我们接下来要说的 ThreadLocal,通过使用 ThreadLocal,我们就可以使变量X在多线程并发的情况下也能线程安全的使用变量X并且不需要上锁,而且做到各个线程之间相互隔离,达到在同一个线程中任何时刻都能够获取到变量X的效果。
2. ThreadLocal 代码举例
如下代码,我都做了一些注释,应该不难理解,所以就不做过多赘述了。
public class WeakReferenceTest {public static void main(String[] args) {// 定义一个 ThreadLocal 全局变量 tlThreadLocal tl = new ThreadLocal();// 创建一个线程new Thread(() -> {// 向 tl 对象中存放一个对象tl.set(new WeakReferenceTest());// 存放对象之后获取,看能否获取成功System.out.println(tl.get()+"存放当前类对象的线程获取存放的类对象");}).start();// 再创建一个新的线程new Thread(() -> {// 让该线程睡1秒,保证钱一个线程一定存储对象成功try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// get 取出上一个线程存放的类对象,看啊可能能否获取到System.out.println(tl.get()+"非存放当前类对象的线程获取存放的类对象");}).start();}
}
然后我们运行上述方法,可以在控制台中得到如下图所示的结果,第一个线程自己向 ThreadLocal 对象中存放创建的类对象时,能够获取得到;但是第二个线程从 ThreadLocal 对象中获取第一个线程存放的类对象时,获取不到,得到的是null。但是我们明明把 ThreadLocal 对象 tl 定义成全局变量了啊,怎么会拿不到呢?
这就是 ThreadLocal 对象特有的属性,从这个例子中,应该也不难看出,ThreadLocal 对象对于线程有自带的隔离性,就算是多个线程共用一个 ThreadLocal 对象,但他们之间存取并不会互相影响。
3. ThreadLocal 源码分析
通过刚才的代码举例演示,同学们也应该简单了解了 ThreadLocal 的特性,那么它是如何做到多县城隔离性的呢?这就要通过阅读它的源码了解底层原理。
3.1 ThreadLocal 的 get 方法源码解析
我们看一下 ThreadLocal 的 set 方法的源码如下所示,方法中它获取了当前线程对象,并用 t 来接收,接受之后调用了 getMap 方法,我们点击跟进查看一下 getMap 方法的源码
如下所示,该方法在 ThreadLocal 类中,找到了 getMap 方法,该方法源码注释最后一行也说了,方法返回值是一个 Map 集合。
方法 return t.threadLocals ,我们点击查看一下它到底是什么东西,如下所示
此时可以看到,我们跳转到了 Thread 类中,源码中 threadLocals 默认为null,它的类型是 ThreadLocalMap,我们点击它查看一下,
此时又跳转到了 ThreadLocal 类中,ThreadLocalMap 是 ThreadLocal 类中的一个内部类,它维护了一个 Map 数组,INITIAL_CAPACITY 初始容量为16,
说明了在 Java 底层,每个Thread 线程对象底层都维护了一个 Map 数组
3.2 ThreadLocal 的 set 方法源码解析
然后下面对 Map 做判断,如果 Map 集合不为空,说明已经存在,则将(this,value)存入其中,认真分析,此时的 this 是什么,是方法的调用者,也就是说 ThreadLocal 的对象 tl 是 Map 集合的 key,value值就是我们方法传入的 value值;
点击跟如查看 set 方法的源码,这里它有一个 Entry,Entry最终存放到了 Map 集合中去,其实一个 Entry 对象就是 Map 集合中的一条记录,Entry 对象内部就是KV键值对,K就是 ThreadLocal 对象,V 就是方法传递过来的值。
下面我们点击 Entry 查看,发现 Entry 是 ThreadLocalMap 类中的内部了,并且该类继承了 WeakReference<>弱引用类, 现在我们发现,ThreadLocal 竟然与弱引用有所关联,并且调用了父类super的方法,所以也就是说他创建的对象引用类型是弱引用类型。
这里补充一点,如果有同学不懂什么是弱引用,可以去看我的另一篇文章,对强引用,弱引用,软引用,虚引用均有所介绍。建议先搞明白什么是弱引用再来学习ThreadLocal,有助于更深入的理解 ThreadLocal 的原理。
强引用,弱引用,软引用,虚引用它们有什么区别?你知道吗?-CSDN博客https://blog.csdn.net/m0_70325779/article/details/133268853?spm=1001.2014.3001.5501
3.3 ThreadLocal 的 createMap 方法源码解析
接着刚才的 3.1 ,如果 Map 集合为空,说明当前线程应该是首次设置 ThreadLocal 属性,所以需要调用 createMap 方法先将当前线程的 Map 集合创建出来,然后再将 value 值设置其中。流程与 if 语句中差不多,都是若引用类型对象。
createMap 源码如下所示,这里它创建了一个 ThreadLocalMap 集合
点击 ThreadLocal 的带参构造,即可跳转至如下界面,这里底层 new 了一个大小为 16 的 Map 集合
3.4 ThreadLocal 的 set 方法总结
经过上面三点的说明,我画了一个的简化图,
(1)程序中我们 new 一个 ThreadLocal 对象用 tl 接收,也可以 new 多个;
(2)每个线程内部都有一个 tls 属性指向独属于自己的那个 Map 集合;
(3)当我们调用 tl 对象 set 方法的时候,实际上底层会创建一个 Entry 键值对对象,K是 set 方法的调用者 tl,V 则是我们要保存的 value 值;
(4)在进行 set 存放操作的时候底层创建的 Entry 对象则是弱引用类型,存放在 Map 集合中
4. 为什么Entry要使用弱引用指向ThreadLocal
经过上面的分析,我们知道了,Map 集合中 Entry 的 key 采用弱引用的方式指向 ThreadLcoal 对象,但是为什么要采用弱引用呢?
答案是因为弱引用可以巧妙地解决 ThreadLocal 带来的内存泄漏问题。
我来给大家说明一下,假设现在我的程序中使用 ThreadLocal tl = new ThreadLocal() 定义了一个 ThreadLocal 对象,并且在当线程执行了 tl.set 将 tl 存储到了当前线程中,随着程序的运行,我们不再需要 ThreadLocal 对象了,于是我们将 tl 设置为空,我们希望垃圾回收期将 ThreadLocal 对象回收。
但是,垃圾回收器真的能将 ThreadLocal 对象回收吗?
如果 Entry 对象中的 key 采用了强引用的方式指向 ThreadLocal 对象,即使将 tl 设置为 null,ThreadLocal 对象也不能被回收,因为 Entry 中的 key 仍然指向它,所以 ThreadLocal 就会作为垃圾一直存在于内存中不能被垃圾回收器回收,除非当前线程结束运行,Map 集合对象被回收,ThreadLocal 对象也跟着被回收。但在实际业务场景中,有些线程会一直运行,那么 ThreadLocal 也会一直存在于内存中,如果有很多的 ThreadLocal 对象都是这样不能被回收存在于内存中,就会造成内存泄漏。
如果 Entry 中的 key 以弱引用的方式指向 ThreadLocal 对象,当 tl 对象设置为 null 时,ThreadLocal 对象就只剩下弱引用指向它,当垃圾回收器遇到 ThreadLocal 对象时,就可以将它回收,避免了内存泄露。
5. 如果将 tl 设置为 null,一定要将Map中的对应记录remove
上面说到了 Entry 对象中的 key 采用弱引用的方式解决了 ThreadLocal 可能产生的内存泄漏问题,但是,产生内存泄露的不只是 ThreadLocal。
各位同学现在仔细想想,还是接着上面的第四点,我将 tl 设置为 null,tl 与 ThreadLocal 对象之间的引用就会断开,那么此时线程内部的 Map 集合保存的 ThreadLocal 那条记录的 key 也会变成 null,如下图所示。
那么现在我们就需要注意一点啦!!!
Map 集合中 Entry 的 key 变成了 null,那么此时对应的 value 值我们是访问不到的,既然访问不到,也就没有用了,value值也会变成垃圾对象,需要被垃圾回收器回收。所以如果在程序中将 ThreadLocal 对象设置为 null 的时候,同时也需要将 Map 集合中 key 为 null 的记录全部 remove,避免 value 值无法被回收造成内存泄露。
6. 线程池中的线程使用完毕归还之前清除Map
在实际开发的过程中,我们往往不会去创建新的线程,而是使用线程池中的线程,在使用完毕之后再归还到线程池,避免线程的重复创建和销毁。
线程池的使用也随之带来了另一个问题——线程在归还到线程池之前一定要将 Map 集合清除。
原因很简单,假设现在我从线程池中拿到了一个线程来使用,并在使用的过程中向 map 集合中存放了一些 ThreadLocal 对象,我在使用完线程之后不将 Map 集合清除直接归还到了线程池中。当下次再有其它业务使用线程时,再向 Map 集合中存放 ThreadLocal 对象,如果 key 相同,就会把原来的 ThreadLocal 对象覆盖;还有一种情况就是直接从 Map 集合中取 ThreadLocal 对象,那么取出来的就是之前的,很有可能会产生错误,对业务造成影响。
7. ThreadLocal 广泛应用于线程池
如果你有阅读过线程池的源码,你就会发现线程池中广泛应用到了 ThreadLocal,并且线程池中的线程完成任务之后,首先就会清理线程内部的 Map 集合,防止对下一次的线程操作产生影响。
而且 Spring 框架中的 @Transaction 事务注解;
线程池中的部分源码,都应用到了ThreadLocal;
除此之外,一些集合中为了防止造成内存泄漏,也会加入 ThreadLocal 。
ThreadLocal 也是面试中可能会问到的一个比较重要的知识点,如果能看懂本篇文章,应对面试可以说绰绰有余了。
相关文章:

深挖 ThreadLocal 底层原理?它有什么用?学会之后手撕面试官
目录 1. ThreadLocal 的主要功能? 2. ThreadLocal 代码举例 3. ThreadLocal 源码分析 3.1 ThreadLocal 的 get 方法源码解析 3.2 ThreadLocal 的 set 方法源码解析 3.3 ThreadLocal 的 createMap 方法源码解析 3.4 ThreadLocal 的 set 方法总结 4. 为什么En…...

sort()排序函数(c++)
文章目录 sort()排序函数(c)一、原理二、使用方法(一)头文件(二)使用语法1.方式一(默认)2.方式二:定义升序或降序3.方式三:自定义 sort()排序函数(…...

如何评估测试用例的优先级?
评估测试用例的优先级,有助于我们及早发现和解决可能对系统稳定性和功能完整性产生重大影响的问题,助于提高测试质量,提高用户满意度。 如果没有做好测试用例的优先级评估,往往容易造成对系统关键功能和高风险场景测试的忽略&…...

510758-28-8,用于标记蛋白质和酶的配体TBTA
产品简介:Tris(benzyltriazolylmethyl)amine (TBTA)是一种配体,能作为生化工具用于标记蛋白质和酶。 CAS号:510758-28-8 中文名:三[(1-苄基-1H-1,2,3-三唑-4-基)甲基]胺 英文名:TBTA 化学式:C30H30N10…...

Jtti:云服务器ftp不能访问端口如何解决
如果您的云服务器上的FTP服务无法访问端口,可能有多种原因导致这种情况。以下是一些可能的解决方法: 检查FTP服务状态: 首先,请确保您的FTP服务器正在运行。您可以使用以下命令来检查FTP服务器的状态,具体命令可能因FT…...

云服务器租用价格表概览_阿里云腾讯云华为云
云服务器租用价格多少钱一年?阿腾云分享阿里云、腾讯云和华为云的云服务器租用价格表:阿里云2核2G服务器108元一年起、腾讯云2核2G3M带宽轻量服务器95元一年、华为云2核2G3M云耀L实例89元一年起,阿腾云分享更多关于云服务器租用价格明细&…...

E. Iva Pav -前缀和 + 二分 +位运算
题面 分析: 赛时一直纠结于与运算前缀和不可逆,导致没有思路,但是发现行不通并没有及时思考别的解决办法导致一条路走到黑,阻碍了自己的思维,在今年的网络赛赛时也是一样,行不通的时候就没心思去重新想其…...

新手学习:ArcGIS对shp文件裁剪
新手学习:ArcGIS对SHP文件裁剪 新手学习 记录每个步骤,因为有很多控件可能刚开始还不熟悉,根本不知道在哪里,所以写的比较详细。 1.添加要裁剪的shp文件 2.查看shp文件的地理坐标系 双击shp文件,就可以查看shp文件的…...

Java 设计模式——抽象工厂模式
目录 1.概念2.结构3.实现4.优缺点5.使用场景6.模式扩展7.JDK源码解析——Collection.iterator方法 1.概念 (1)Java 设计模式——工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机等。这些工厂只生产同种类产品…...

如何使用ChatGPT构建一个Web应用程序?
围绕ChatGPT的最大卖点之一是它可以成为一种有效的编程工具。其想法是这样的:你用自然语言描述需求,该聊天机器人生成满足该需求的代码。但是ChatGPT在这方面到底有多好呢? 还有什么比亲自测试一下更好的方法呢?我们让ChatGPT从头…...

关闭手机广告的步骤
关闭手机广告的步骤 小米 1.设置→小米账号→声明与条款→系统广告→系统工具广告→关闭 2.设置→应用设置→应用管理→右上角三个点→设置→关闭“应用升级提醒”&“资源推荐” 3.桌面左滑打开负一屏→划到底部→设置→服务管理→选择关闭项目 4.桌面→打开任意文件夹…...

【Verilog 教程】6.6Verilog 仿真激励
关键词:testbench,仿真,文件读写 Verilog 代码设计完成后,还需要进行重要的步骤,即逻辑功能仿真。仿真激励文件称之为 testbench,放在各设计模块的顶层,以便对模块进行系统性的例化调用进行仿真…...

Win/Mac版Scitools Understand教育版申请
这里写目录标题 前言教育版申请流程教育账号申请 前言 上篇文章为大家介绍了Scitools Understand软件,通过领取的反馈来看有很多朋友都想用这个软件,但是我的网盘里只存了windows的pojie版,没有mac版的,我没有去网上找相关的资源…...

第十四届蓝桥杯大赛软件赛决赛 C/C++ 大学 B 组 试题 C: 班级活动
[蓝桥杯 2023 国 B] 班级活动 【问题描述】 小明的老师准备组织一次班级活动。班上一共有 n n n 名( n n n 为偶数)同学,老师想把所有的同学进行分组,每两名同学一组。为了公平,老师给每名同学随机分配了一个 n n …...

YOLOv8改进新颖的Gather-and-Distribute机制,低阶高阶新颖融合,增强了多尺度特征融合能力,实现了延迟和准确性的理想平衡
💡本篇内容:YOLOv8改进新颖的Gather-and-Distribute机制,低阶高阶新颖融合,增强了多尺度特征融合能力,实现了延迟和准确性的理想平衡 💡🚀🚀🚀本博客 改进源代码改进 适用于 YOLOv8 按步骤操作运行改进后的代码即可 💡本文提出改进 原创 方式:二次创新,YOL…...

面试算法13:二维子矩阵的数字之和
题目 输入一个二维矩阵,如何计算给定左上角坐标和右下角坐标的子矩阵的数字之和?对于同一个二维矩阵,计算子矩阵的数字之和的函数可能由于输入不同的坐标而被反复调用多次。例如,输入图2.1中的二维矩阵,以及左上角坐标…...

Vue安装插件时候中遇到冲突依赖解决方案
错误如下: npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: vue/eslint-config-standard6.1.0 npm ERR! Found: eslint-plugin-vue8.7.1 npm ERR! node_modules/eslint-plugin-vue npm ERR! dev eslint-pl…...

realloc函数应用IO泄露体验
本题主要介绍realloc函数,平时我们使用realloc最多便是在打malloc_hook–>onegadget的时候,使用realloc_hook调整onegadget的栈帧,从而getshell。 在realloc函数中,也能像malloc一样创建堆,并且比malloc麻烦一些&a…...

(c语言)野指针
#include<stdio.h> //野指针 int* test() { int a 10; return &a; } int main() { //野指针一: int* p; *p 10; //非法访问内存 //p没有初始化,就意味着没有明确的指向 //一个局部变量不初始化的话ÿ…...

【Git】轻松学会 Git(一):掌握 Git 的基本操作
文章目录 前言一、创建 Git 本地仓库1.1 什么是仓库1.2 创建本地仓库1.3 .git 目录结构 二、配置 Git三、认识 Git 的工作区、暂存区和版本库3.1 什么是 Git 的工作区、暂存区和版本库3.2 工作区、暂存区和版本库之间的关系 四、添加文件4.1 添加文件到暂存区和版本库中的命令4…...

rust trait对象
在拥有继承的语言中,可以定义一个名为shape的基类,该类上有一个draw方法。其他的类比如Button、SelectBox继承shape。它们各自覆盖draw方法。调用这些子类的draw方法时,就可以把它们统一当作shape来使用。不过Rust并没有继承,如果…...

Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 在人类的发展进化中,时间是一个非常重要神秘的物质量。任何事物都是在时间的长河中流淌发生、发展、变化。我们进行驱动开发中对时间的定义和使用也是…...

Centos服务在服务器重启后自启
以Dolphin为例 打开rc.local文件以编辑: sudo vi /etc/rc.d/rc.local在文件中添加您的启动命令。在您的情况下,要添加的命令如下: sh /opt/dolphinscheduler/zookeeper/bin/zkServer.sh start sh /opt/dolphinscheduler/dolphinscheduler/…...

慢性疼痛治疗服务公司Kindly MD申请700万美元纳斯达克IPO上市
来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,慢性疼痛治疗服务公司Kindly MD近期已向美国证券交易委员会(SEC)提交招股书,申请在纳斯达克IPO上市,股票代码为(KDLY),Kindly MD计划通过…...

代码随想录 Day6 哈希 LeetcodeT454 四数之和II T383赎金信 T15 三数之和 T18 四数之和
本文代码思路来源于: 代码随想录 前言 希望大家在刷这部分题的时候先熟悉熟悉哈希结构的基本常用api,比较方便理解. LeetCode T454 四数之和 题目链接:454. 四数相加 II - 力扣(LeetCode) 题目思路 暴力解法仍然是遍历四个数组解决此题, 哈希的思路有…...

干货速来|教你如何撰写毕业论文
撰写毕业论文对于正常大学毕业至关重要。毕业论文是对学生在大学期间所学知识的综合运用和深入研究的体现,也是对学术能力和独立思考能力的考验。 撰写毕业论文的过程需要学生投入大量的时间和精力,包括选题、文献综述、研究方法选择、数据收集和分析、…...

【ROS 2】-2 话题通信
飞书原文链接: Docs...

Unity之NetCode多人网络游戏联机对战教程(2)--简单实现联机
文章目录 1.添加基本组件2.创建NetworkManager组件3.创建Player4.创建地面5.创建GameManager6.编译运行7. 测试联机后话 1.添加基本组件 NetworkManagerPlayerScene 2.创建NetworkManager组件 创建一个空物体,命名为NetworkManager 选择刚刚创建的NetworkManager…...
makdown文法
这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

新手程序员怎么接单?
程序员如何在自己年富力强的时候,最大化发挥自己的能力?将超能力转化为“钞能力”? 有人还在苦哈哈当老黄牛,一身使不完的牛劲,有人已经另辟蹊径,开创了自己的一片致富小天地。 接单找兼职,就…...