工作面试中经常遇到ThreadLocal , 但是很多同学并不了解ThreadLocal实现原理 , 到底为什么会发生内存泄漏也是一知半解?今天一灯带你深入剖析ThreadLocal源码 , 总结ThreadLocal使用规范 , 解析ThreadLocal高频面试题 。
1. ThreadLocal是什么ThreadLocal是线程本地变量 , 就是线程的私有变量 , 不同线程之间相互隔离 , 无法共享 , 相当于每个线程拷贝了一份变量的副本 。
目的就是在多线程环境中 , 无需加锁 , 也能保证数据的安全性 。
2. ThreadLocal的使用/** * @author 一灯架构 * @apiNote ThreadLocal示例 **/public class ThreadLocalDemo {// 1. 创建ThreadLocalstatic ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {// 2. 给ThreadLocal赋值threadLocal.set("关注公众号:一灯架构");// 3. 从ThreadLocal中取值String result = threadLocal.get();System.out.println(result); // 输出 关注公众号:一灯架构// 4. 删除ThreadLocal中的数据threadLocal.remove();System.out.println(threadLocal.get()); // 输出null}}
ThreadLocal的用法非常简单 , 创建ThreadLocal的时候指定泛型类型 , 然后就是赋值、取值、删除值的操作 。
不同线程之间 , ThreadLocal数据是隔离的 , 测试一下:
/** * @author 一灯架构 * @apiNote ThreadLocal示例 **/public class ThreadLocalDemo {// 1. 创建ThreadLocalstatic ThreadLocal<Integer> threadLocal = new ThreadLocal<>();public static void main(String[] args) {IntStream.range(0, 5).forEach(i -> {// 创建5个线程 , 分别给threadLocal赋值、取值new Thread(() -> {// 2. 给ThreadLocal赋值threadLocal.set(i);// 3. 从ThreadLocal中取值System.out.println(Thread.currentThread().getName()+ "," + threadLocal.get());}).start();});}}
输出结果:
Thread-2,2Thread-4,4Thread-1,1Thread-0,0Thread-3,3
可以看出不同线程之间的ThreadLocal数据相互隔离 , 互不影响 , 这样的实现效果有哪些应用场景呢?
3. ThreadLocal应用场景ThreadLocal的应用场景主要分为两类:
- 避免对象在方法之间层层传递 , 打破层次间约束 。
比如用户信息 , 在很多地方都需要用到 , 层层往下传递 , 比较麻烦 。这时候就可以把用户信息放到ThreadLocal中 , 需要的地方可以直接使用 。
- 拷贝对象副本 , 减少初始化操作 , 并保证数据安全 。
比如数据库连接、Spring事务管理、SimpleDataFormat格式化日期 , 都是使用的ThreadLocal , 即避免每个线程都初始化一个对象 , 又保证了多线程下的数据安全 。
/** * @author 一灯架构 * @apiNote ThreadLocal示例 **/public class ThreadLocalDemo {// 1. 创建ThreadLocalstatic ThreadLocal<SimpleDateFormat> threadLocal =ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));public static void main(String[] args) {IntStream.range(0, 5).forEach(i -> {// 创建5个线程 , 分别从threadLocal取出SimpleDateFormat , 然后格式化日期new Thread(() -> {try {System.out.println(threadLocal.get().parse("2022-11-11 00:00:00"));} catch (ParseException e) {throw new RuntimeException(e);}}).start();});}}
4. ThreadLocal实现原理ThreadLocal底层使用ThreadLocalMap存储数据 , 而ThreadLocalMap内部是一个数组 , 数组里面存储的是Entry对象 , Entry对象里面使用key-value存储数据 , key是ThreadLocal实例对象本身 , value是ThreadLocal的泛型对象值 。
经验总结扩展阅读
- 全方位剖析宝宝湿疹
- 深入剖析Sgementation fault原理
- Java程序员必会Synchronized底层原理剖析
- 硬核字幕组是什么意思?
- 硬核是什么梗?
- 硬核颜值是什么意思?
- 硬核父母是什么意思?
- 硬核奶奶是什么意思?
- 硬核祖母是什么意思?
- 硬核女装是什么意思?