悠哉杂学 - Thread
type: channel
link: https://uinit.cn/index.php/tag/Thread/
items: 全方位，多角度理解ThreadLocal

全方位，多角度理解ThreadLocal
type: item
date: 2021-08-26T05:58:00+08:00
description: [scode type="share"]来源：blog.csdn.net/zzg1229059735/article/details/82715741[/scode]本次给大家介绍重要的工具ThreadLocal。讲解内容如下，同时介绍什么场景下发生内存泄漏，如何复现内存泄漏，如何正确使用它来避免内存泄漏。ThreadLocal是什么？有哪些用途？ThreadLocal如何使用ThreadLocal原理ThreadLocal使用有哪些坑及注意事项1.ThreadLocal是什么？有哪些用途？首先介绍Thread类中属性threadLocals:/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class.*/ ThreadLocal.ThreadLocalMap threadLocals = null; 我们发现Thread并没有提供成员变量threadLocals的设置与访问的方法，那么每个线程的实例threadLocals参数我们如何操作呢？这时我们的主角：ThreadLocal就登场了。所以有那么一句总结：ThreadLocal是线程Thread中属性threadLocals的管理者。也就是说我们对于ThreadLocal的get, set，remove的操作结果都是针对当前线程Thread实例的threadLocals存，取，删除操作。类似于一个开发者的任务，产品经理左右不了，产品经理只能通过技术leader来给开发者分配任务。下面再举个栗子，进一步说明他们之间的关系：每个人都一张银行卡每个人每张卡都有一定的余额。每个人获取银行卡余额都必须通过该银行的管理系统。每个人都只能获取自己卡持有的余额信息，他人的不可访问。映射到我们要说的ThreadLocalcard类似于Threadcard余额属性，卡号属性等类似于Treadlocal内部属性集合threadLocalscardManager类似于ThreadLocal管理类那ThreadLocal有哪些应用场景呢？其实我们无意间已经时时刻刻在使用ThreadLocal提供的便利，如果说多数据源的切换你比较陌生，那么spring提供的声明式事务就再熟悉不过了，我们在研发过程中无时无刻不在使用，而spring声明式事务的重要实现基础就是ThreadLocal，只不过大家没有去深入研究spring声明式事务的实现机制。后面有机会我会给大家介绍spring声明式事务的原理及实现机制。原来ThreadLocal这么强大，但应用开发者使用较少，同时有些研发人员对于ThreadLocal内存泄漏，等潜在问题，不敢试用，恐怕这是对于ThreadLocal最大的误解，后面我们将会仔细分析，只要按照正确使用方式，就没什么问题。如果ThreadLocal存在问题，岂不是spring声明式事务是我们程序最大的潜在危险吗？2.ThreadLocal如何使用为了更直观的体会ThreadLocal的使用我们假设如下场景我们给每个线程生成一个ID。一旦设置，线程生命周期内不可变化。容器活动期间不可以生成重复的ID我们创建一个ThreadLocal管理类：测试程序如下：我们同一个线程不断get，测试id是否变化，同时测试完成后我们就将其释放掉。在主程序中我们开启多个线程测试不通线程之间是否会影响不出意外我们的结果为：结果：确实是不同线程间id不同，相同线程id相同。3.ThreadLocal原理①ThreadLocal类结构及方法解析：上图可知：ThreadLocal三个方法get, set , remove以及内部类ThreadLocalMap②ThreadLocal及Thread之间的关系：从这张图我们可以直观的看到Thread中属性threadLocals，作为一个特殊的Map，它的key值就是我们ThreadLocal实例，而value值这是我们设置的值。③ThreadLocal的操作过程：我们以get方法为例:其中getMap(t)返回的就上当前线程的threadlocals，如下图，然后根据当前ThreadLocal实例对象作为key获取ThreadLocalMap中的value，如果首次进来这调用setInitialValue()set的过程也类似：注意：ThreadLocal中可以直接t.threadLocals是因为Thread与ThreadLocal在同一个包下，同样Thread可以直接访问ThreadLocal.ThreadLocalMap threadLocals = null;来进行声明属性。4.ThreadLocal使用有哪些坑及注意事项我经常…