栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java ThreadLocal源码详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java ThreadLocal源码详解

ThreadLocal

Thread类的定义中有ThreadLocal.ThreadLocalMap threadLocals = null;

说明每个线程自己保存一个 ThreadLocal.ThreadLocalMap 类

每次使用ThreadLocal的get()或set(), 都是用ThreadLocal作为key获取或存放map的value

ThreadLocal可以避免在一个线程类中的方法中重复传递参数

public static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>();
void test(){
	THREAD_LOCAL.set("wupx");
	String v = THREAD_LOCAL.get();
}
Set()

ThreadLocal 的 set ()

先获取当前线程

获取线程的ThreadLocalMap

map为null 就 createMap(t, value);

不为null就map.set(this, value);

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        map.set(this, value);
    } else {
        createMap(t, value);
	}
}
    
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

get()

同样是去找当前thread的ThreadLocalMap, 对map进行getEntry()

    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();
    }
ThreadLocal.ThreadLocalMap

底层实现是Entry[], 下面是entry的定义

static class Entry extends WeakReference> {
    
    Object value;

    Entry(ThreadLocal k, Object v) {
        super(k);
        value = v;
    }
}

ThreadLocal作为key, 并且是弱引用, 可以通过WeakReference的父类REference的get()来获取

用ThreadLocal的nextHashCode作为下标, Object类作为value, 放入entry中

这意味着每个ThreadLocal类在每个线程中都能找到对应的value

 ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
     // ...
     private static final int INITIAL_CAPACITY = 16;
     // ...
     // 新建一个16位的Entry[] 
     table = new Entry[INITIAL_CAPACITY];
     // 计算firstkey的hash值
     int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
     // 将entry放入数组中
     table[i] = new Entry(firstKey, firstValue);
     // 设置table中已放入entry的数量
     size = 1;
     // 设置哈希表扩容的阈值
     setThreshold(INITIAL_CAPACITY);
 }
ThreadLocal 内存泄漏

threadLocalMap 中保存的 key 值是弱引用, GC时被回收

但是 Entry 被 threadLocalMap 对象引用,threadLocalMap 对象又被 Thread 对象所引用

当 Thread 一直不终结的话,value 对象就会一直存在于内存中,也就导致了内存泄漏

在使用完 ThreadLocal 变量后,需要我们手动 remove 掉

源码 :

    public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null) {
             m.remove(this);
         }
     }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/966869.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号