【Java并发】ThreadLocal的实现原理&源码解析

1.ThreadLocal是什么?

ThreadLocal 是 Java 中的一个线程局部变量类。它提供了一种在多线程环境下,为每个线程独立存储数据的机制。

并且:
ThreadLocal 通过为每个线程创建一个独立的副本来实现线程隔离。每个线程都可以独立地修改和访问自己的副本,而不会影响其他线程的副本。每个线程都可以像访问普通变量一样访问 ThreadLocal 对象,而不必担心线程安全问题。

2.ThreadLocald实现原理&源码解析

ThreadLocal本质来说就是一个·线程内部存储类·,从而让多个线程只操作自己内部的值,从而实现线程数据隔离

基本方法有:

  1. set(value) 设置值
  2. get() 获取值
  3. remove() 清除值

set(value) 设置值
首先获取当前线程,然后获取当前线程的 ThreadLocalMap 对象。如果 ThreadLocalMap 存在,就将当前 ThreadLocal 对象作为,将值 value 存储到其中;否则,创建一个新的 ThreadLocalMap,并将当前 ThreadLocal 对象和值 value 存储到其中。

/**
 * 设置线程局部变量的值。
 * @param value 要设置的值
 */
public void set(T value) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 获取当前线程的 ThreadLocalMap,用于存储线程局部变量
    ThreadLocalMap map = getMap(t);
    if (map != null)
        // 如果 ThreadLocalMap 存在,则将当前 ThreadLocal 对象作为键,将 value 作为值存储起来
        map.set(this, value);
    else
        // 如果 ThreadLocalMap 不存在,则创建一个新的 ThreadLocalMap,并将当前 ThreadLocal 对象和 value 存储到其中
        createMap(t, value);
}

get() 获取值

通过ThreadLocal 对象去取对应的value

首先,获取当前线程并获取其对应的 ThreadLocalMap 对象。如果 ThreadLocalMap 存在,则通过调用 getEntry(this) 方法获取当前 ThreadLocal 对象对应的条目。如果条目存在,则返回条目中存储的值。如果线程局部变量不存在,则调用 setInitialValue() 方法返回初始值。

/**
 * 获取线程局部变量的值。
 * @return 线程局部变量的值,如果不存在则返回初始值
 */
public T get() {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 获取当前线程的 ThreadLocalMap,用于存储线程局部变量
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 通过 ThreadLocalMap 获取对应的条目
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            // 如果条目存在,则返回条目中存储的值
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    // 如果线程局部变量不存在,则返回初始值
    return setInitialValue();
}

remove() 清除值

根据ThreadLocal 删除对

     /**
 * 从当前线程的 ThreadLocalMap 中移除当前 ThreadLocal 对象对应的条目。
 */
public void remove() {
    // 获取当前线程的 ThreadLocalMap
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null) {
        // 如果 ThreadLocalMap 存在,则调用 remove(this) 方法移除当前 ThreadLocal 对象对应的条目
        m.remove(this);
    }
}

3.ThreadLocal-内存泄露问题

什么是内存泄漏
内存泄漏是指在程序中,不再使用的对象仍然被占用着内存无法被垃圾回收器回收释放,导致内存占用逐渐增加,最终可能导致内存耗尽性能下降。

Java对象中的四种引用类型:强引用软引用弱引用虚引用

强引用:最为普通的引用方式,表示一个对象处于有用且必须的状态,如果一个对象具有强引用,则GC并不会回收它。即便堆中内存不足了,宁可出现OOM,也不会对其进行回收

在这里插入图片描述

弱引用:表示一个对象处于可能有用且非必须的状态。在GC线程扫描内存区域时,一旦发现弱引用,就会回收到弱引用相关联的对象。对于弱引用的回收,无关内存区域是否足够,一旦发现则会被回收

在这里插入图片描述
出现内存泄漏的原因:

  1. 长期持有:如果在 ThreadLocal 中设置的值长时间持有,而没有进行及时清理和释放可能导致内存泄漏。(只要线程不结束,就一直存在)

  2. 线程结束不清理:如果在线程结束没有正确地清理 ThreadLocal,可能会导致内存泄漏。因为线程结束后,对应的 ThreadLocalMap 对象不会被垃圾回收,其中的 ThreadLocal 对象无法释放。

  3. 对象强引用:每一个Thread维护一个ThreadLocalMap,在ThreadLocalMap中的Entry对象继承了WeakReference。其中key为使用弱引用的ThreadLocal实例,value为线程变量的副本

在这里插入图片描述
解决办法就是:使用完ThreadLocal后主动 remove 释放 key,value

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值