当前位置:网站首页>面试官:ThreadLocal使用场景有哪些?内存泄露问题如何避免?
面试官:ThreadLocal使用场景有哪些?内存泄露问题如何避免?
2022-07-28 17:06:00 【nuzzzzz】
ThreadLocal使用场景有哪些?

Thread类中有两个变量threadLocals和inheritableThreadLocals,二者都是ThreadLocal内部类ThreadLocalMap类型的变量,我们通过查看内部内ThreadLocalMap可以发现实际上它类似于一个HashMap。在默认情况下,每个线程中的这两个变量都为null:
ThreadLocal.ThreadLocalMap threadLocals = null;ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;只有当线程第一次调用ThreadLocal的set或者get方法的时候才会创建他们。
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue();} ThreadLocalMap getMap(Thread t) { return t.threadLocals;}除此之外,每个线程的本地变量不是存放在ThreadLocal实例中,而是放在调用线程的ThreadLocals变量里面。也就是说,ThreadLocal类型的本地变量是存放在具体的线程空间上,其本身相当于一个装载本地变量的载体,通过set方法将value添加到调用线程的threadLocals中,当调用线程调用get方法时候能够从它的threadLocals中取出变量。如果调用线程一直不终止,那么这个本地变量将会一直存放在他的threadLocals中,所以不使用本地变量的时候需要调用remove方法将threadLocals中删除不用的本地变量,防止出现内存泄漏。
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value);}public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this);}ThreadLocal内存泄露问题如何避免?
每个Thread都有一个
ThreadLocal.ThreadLocalMap的map,该map的key为ThreadLocal实例,它为一个弱引用,我们知道弱引用有利于GC回收。当ThreadLocal的key == null时,GC就会回收这部分空间,但是value却不一定能够被回收,因为他还与Current Thread存在一个强引用关系,如下

由于存在这个强引用关系,会导致value无法回收。如果这个线程对象不会销毁那么这个强引用关系则会一直存在,就会出现内存泄漏情况。所以说只要这个线程对象能够及时被GC回收,就不会出现内存泄漏。如果碰到线程池,那就更坑了。 那么要怎么避免这个问题呢? 在前面提过,在ThreadLocalMap中的setEntry()、getEntry(),如果遇到key == null的情况,会对value设置为null。当然我们也可以显示调用ThreadLocal的remove()方法进行处理。 下面再对ThreadLocal进行简单的总结:
- ThreadLocal 不是用于解决共享变量的问题的,也不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制。这点至关重要。
- 每个Thread内部都有一个ThreadLocal.ThreadLocalMap类型的成员变量,该成员变量用来存储实际的ThreadLocal变量副本。
- ThreadLocal并不是为线程保存对象的副本,它仅仅只起到一个索引的作用。它主要是为每一个线程隔离一个类的实例,这个实例的作用范围仅限于线程内部。
边栏推荐
- Golang concurrent lock
- Go's sleep
- MYSQL入门与进阶(八)
- Random talk on GIS data (VI) - projection coordinate system
- Ue5 gas learning notes 1.6 skills gameplay ability
- redis优势以及数据结构相关知识
- Ue5 gas learning notes 1.4 attribute set
- Introduction and advanced level of MySQL (8)
- Go's walk library reports an error
- 2022年中国企业服务产业市场行情
猜你喜欢

直播|StarRocks 技术内幕 :低基数全局字典优化

十进制转二进制进阶版(可转化负数以及边界值)

2022-07-27 study notes of group 4 self-cultivation class (every day)

NPM cannot recognize the "NPM" item as the name of a cmdlet, function, script file, or runnable program. Please check the spelling of the name. If the path is included, make sure the path is correct,

npm 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。

MYSQL入门与进阶(五)

Performance parameters of spectrum analyzer

Six countries in Europe and the United States launched an express line product to optimize the "end-to-end" performance service on the 5th

Introduction and advanced level of MySQL (5)

MYSQL入门与进阶(三)
随机推荐
haproxy实现代理配置
leetcode 二叉树类
Introduction and advanced level of MySQL (5)
LeetCode_96_不同的二叉搜索树
Look at Devops construction from SRE
.net WCF WF4.5 状态机、书签与持久化
Bubble sorting and Related videos
insight! Baidu pushed redis ceiling notes, which was originally understood by the database
数字化转型中的DevOps——弹性合作
从 SRE 看 DevOps 建设
408复习策略(强化阶段)
MYSQL入门与进阶(二)
明德生物:公司暂未有产品被列入WHO推荐清单
SQL Server stuff and for XML path
@Autowired与@Resource区别
What are the conditions for zero foundation learning software testing?
UE5 GAS 学习笔记 1.10 预测(Prediction)
NDK series (5): from introduction to practice, JNI explodes the liver and explains everything in detail!
Principle, classification and requirements of antenna
Multithreading and high concurrency -- source code analysis AQS principle