ThreadLocal-全概念解析
介绍
ThreadLocal
提供线程局部变量,ThreadLocal实例通常是线程私有静态字段,使用的目的是希望将线程与状态关联起来。与JMM中局部变量有几分相似之处,但是不用写回主内存(如果违反,那就线程不安全),Thread用完要remove(),特别在线程池的情况下,会出现内存泄漏。
Thread、ThreadLocal、ThreadLocalMap
ThreadLocal.ThreadLocalMap 各自线程拥有自己的Map。
- 注意😒😒😒
思考:为什么要在线程中使用ThreadLocalMap?为什么是Entry数组?
因为一个线程可以拥有多个ThreadLocal,没错,多个ThreadLocal变量。
强、软、弱、虚
强引用:普通对象引用。
Student a=new Student();
a=null;
软引用:内存足够时保留,内存不够时会回收
弱引用:只要gc就回收
虚引用:在对象回收后进行通知,放入引用队列。
什么是内存泄漏?
不再会被使用的对象,不能被回收。
为什么会出现内存泄漏?
key是弱引用,被回收后,value没有被回收。
threadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null, 而value还存在着强引用,只有thead线程退出以后,value的强引用链条才会断掉。
但如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value
永远无法回收,造成内存泄漏。
仔细想想,ThreadLocal 下面这个设计值得学习
- Thead 线程中有ThreadLocalMap
- 在线程内创建ThreadLocal会自动放进ThreadLocalMap
ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("123");
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = t.threadLocals;
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
更新一下,我想给你讲明白ThreadLocal
现在时间2023-07-05-00:37
提前声明,如有理解错误,本人概不负责。😁
面试官:你好同学,简单一个面试题,八股文,来,对象会创建在什么区域?
小涛:堆(简洁明了,不拖泥带水,声音洪亮)
面试官:offer给你了,拿去。😊
面试官:那么假如线程执行过程中发生GC,内存不够了嘛,key不是弱引用嘛,发生GC就会销毁,ThreadLocalMap key会不会被销毁,再说明一下问题也就是说key指向的ThreadLocal会不会被回收?
小涛:如回 如来到底来没来 如来
面试官:offer给你了,拿去。😊,到底回没回收?
首先搞清楚,ThreadLocal 在线程执行过程中,会不会回收?你觉着应不应该被回收,那当然不能被回收,线程中创建的对象放在堆区,线程中局部变量表指向堆区对象,线程执行过程中,指针一直会指向堆区对象(强引用),那么堆中的对象怎么会被回收呢?
那什么时候这些强引用会被销毁呢?线程结束,栈帧弹出,引用是不是没了?假如果ThreadLocalMap 中key是强引用,也就如下图:
那你说说ThreadLocal 对象会不会被回收?那不是有key的强引用嘛。只要ThreadLocalMap不回收,ThreadLocal对象就不会被回收。
设计师设计成弱引用,gc时候发现ThreadLocal对象只有弱引用,那么会直接将对象回收,剩下的ThreadLocalMap话,交给系统进行回收嘛。
面试官:说了这么多,那你说说,现在ThreadLocal为什么会存在内存泄漏的风险?
我:ThreadLocalMap交给系统回收?什么时候回收?value中的对象什么时候释放?ThreadLocalMap不回收,value不会释放。所以我们要养成手动remove的好习惯,当然ThreadLocal里面也做了优化,比如某些时候看到Key被回收时,会释放value。
本文来自博客园,作者:帅气的涛啊,转载请注明原文链接:https://www.cnblogs.com/handsometaoa/p/17467719.html