🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝🍓 更多文章请点击
文章目录
- 一、什么是ThreadLocal?
- 二、源码分析
- 1. 首先看下Thread类
- 2. ThreadLocalMap这是什么?
- 3. ThreadLocal详解
- 三、什么是弱引用呢?
- 3.1 谈谈引用关系都有哪些,区别又是什么?
- 3.2 ThreadLocal为何使用弱引用
- 3.3 内存泄漏是什么,如何避免TheadLocal的内存泄漏?
- 四、总结
一、什么是ThreadLocal?
ThreadLocal
用来提供线程级别变量,变量只对当前线程见,ThreadLocal
通过空间换时间的方案,规避了竞争问题,因为每个线程都有属于自己的变量。- TheadLocal为每个使用该变量的线程单独提供独立的变量副本,具有线程隔离效果。
- 与synchronized的区别
synchronized 与 TheadLocal都可以实现多线程访问,保证线程安全问题。- synchronized 采用当多线程竞争到同一个资源的时候,最终只能够有一个线程访问,采用
时间换空间
的方式,保证安全问题。 - TheadLocal 在每个线程中都自己独立的局部变量,
空间换时间
,相互之间隔离,相比来说TheadLocal效率更高
- synchronized 采用当多线程竞争到同一个资源的时候,最终只能够有一个线程访问,采用
二、源码分析
1. 首先看下Thread类
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
Thread
中有一个 threadLocals
属性表示线程的本地变量
。这个属性的类型是 ThreadLocal.ThreadLocalMap
2. ThreadLocalMap这是什么?
ThreadLocalMap
是 ThreadLocal
的内部类,他是类 Map结构,并用 Entry
封装 K-V
。不同的是 ThreadLocalMap的 Entry的 Key只能是 ThreadLocal
类型对象,并且是一个弱引用
(下面会详细详解)。
也就是说线程
通过一个类Map数据结构ThreadLocal.ThreadLocalMap
来存储属于自己的线程变量。
3. ThreadLocal详解
- ThreadLocal 先对其进行介绍后进行测试。
- ThreadLocalMap
赋值、取值
操作的入口在其外部类ThreadLocal
中。 - 使用时我们只需要操作
ThreadLocal
即可。
set(T )
方法内调用 ThreadLocalMap 的set(this,v)
方法存值。
2. get()
方法内调用 ThreadLocalMap的 getEntry(this)
方法取值
## 4. 测试
public class TestThreadLocal {
public static void main(String[] args) {
ThreadLocal threadLocal = new ThreadLocal();
threadLocal.set("第一次值");
threadLocal.set("第二次值");
System.out.println(threadLocal.get());
}
}
通过set(T)方法可知存储的是当前TheadLocal对象和值,所以新值会替换旧值
三、什么是弱引用呢?
3.1 谈谈引用关系都有哪些,区别又是什么?
-
强引用: 当内存不足时,JVM开始进行GC(垃圾回收),
对于强引用对象,就算出现OOM(内存溢出)也不会对该对象进行回收
。 -
软引用: 当系统内存充足时,不会被回收,当系统内存不足时会被回收,
内存够用就保留,不够用就回收
。 -
弱引用: 比软引用的生存周期更短,只要垃圾回收,
不管JVM的内存空间是否够用,都会回收该对象占用的内存空间。
-
虚引用: 形同虚设,虚引用不会决定对象的生命周期(主要配合队列,在销毁前做一些操作)。
3.2 ThreadLocal为何使用弱引用
容易被GC回收,对于ThreadLocal而言,为最小化减少内存泄漏的可能性和影响,在ThreadLocal的get,set方法被调用的时候,都会清除线程map里面所有key为null的值。
3.3 内存泄漏是什么,如何避免TheadLocal的内存泄漏?
内存泄漏: 申请了内存,但是该内存一直无法释放,申请内存时,发现内存不足,就会报错OOM问题
如何避免
- TheadLocal本身会在get,set时清除key为null的值
- Entry对象本身为弱引用
- 在使用完该对象时,
手动调用remove方法
四、总结
Thread
用类似 Map的ThreadLocal.ThreadLocalMap
数据结构来存储以ThreadLocal
类型的变量为Key
的数值,并用ThreadLocal
来存取删,操作ThreadLocalMap
。- 调用
set(T)
方法时,就是以当前ThreadLocal变量为 key,传入参数为 value,向 ThreadLocal.ThreadLocalMap存数据
- 当我们调用
get()
方法时,就是以当前 ThreadLocal变量为 key,从 ThreadLocal.ThreadLocalMap取对应的数据
- 使用完后记得调用
remove()
方法