推荐链接:
总结——》【Java】
总结——》【Mysql】
总结——》【Redis】
总结——》【Kafka】
总结——》【Spring】
总结——》【SpringBoot】
总结——》【MyBatis、MyBatis-Plus】
总结——》【Linux】
总结——》【MongoDB】
总结——》【Elasticsearch】
一、概念
ThreadLocal可以理解为线程本地变量
,他会在每个线程都创建一个副本
,那么在线程之间访问内部副本变量就行了,做到了线程之间互相隔离
,相比于synchronized的做法是用空间来换时间。
ThreadLocal的本质就是一个Map
,ThreadLocal做为key,将一个数据和本地线程绑定在一起。
二、源码
ThreadLocal有一个静态内部类ThreadLocalMap
,ThreadLocalMap又包含了一个Entry数组
,Entry本身是一个弱引用
,他的key是指向ThreadLocal的弱引用,Entry具备了保存key value键值对的能力。
三、内部结构
四、特点
- 每个Thread中都存储着一个成员变量ThreadLocalMap
- ThreadLocal本身不存储数据,像是一个工具类,基于ThreadLocal去操作ThreadLocalMap
- ThreadLocalMap本身就是基于Entry[]实现的,因为一个线程可以绑定多个ThreadLocal,这样一来,可能需要存储多个数据,所以采用Entry[]的形式实现。
- 每一个现程都自己独立的ThreadLocalMap,再基于ThreadLocal对象本身作为key,对value进行存取
- ThreadLocalMap的key是一个
弱引用
,弱引用的目的是为了防止内存泄露
,如果是强引用那么ThreadLocal对象除非线程结束否则始终无法被回收,弱引用则会在下一次GC的时候被回收
五、内存泄漏问题
Java中4种引用:
强引用:OOM也不清除
软引用:内存不足清除
弱引用:只要GC就清除
虚引用:拿不到引用,构建出来就凉凉~~
1、现象
假如ThreadLocal对象被回收之后,key因为弱引用也会被GC回收掉,同时线程还没有被回收,entry中就存在key为null,但value有值的entry对象,但是内存中的value无法被获取到,同时也无法被回收,就会导致内存泄漏。
2、解决方案
使用TheadLocal完毕后,调用remove方法删除Entry对象
。
六、内存泄漏案例
参考链接:Java——》内存泄露案例文章来源:https://www.toymoban.com/news/detail-702893.html
七、保证原子性
ThreadLocal保证原子性的方式,是不让多线程去操作临界资源
,让每个线程去操作属于自己的数据
。文章来源地址https://www.toymoban.com/news/detail-702893.html
static ThreadLocal tl1 = new ThreadLocal();
static ThreadLocal tl2 = new ThreadLocal();
public static void main(String[] args) {
tl1.set("123");
tl2.set("456");
Thread t1 = new Thread(() -> {
System.out.println("t1:" + tl1.get());
System.out.println("t1:" + tl2.get());
});
t1.start();
System.out.println("main:" + tl1.get());
System.out.println("main:" + tl2.get());
}
到了这里,关于Java——》ThreadLocal的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!