Just do it
专注做自己的事,有想做的事就去做好了
一句话定义

ThreadLocal通过每个线程独有的ThreadLocalMap来存储数据,以ThreadLocal自身为Key,实现线程隔离。

理解过程

ThreadLocal是用于存取当前线程中临时变量的一个工具,Thread中存在ThreadLocalMap的变量,当ThreadLocal设置变量时,先查出当前线程下的ThreadLocalMap,如果为null,则创建ThreadLocalMap,key是当前的ThreadLocal对象,value是要存入的值,再将构建好的ThreadLocalMap赋值给当前线程下的ThreadLocalMap。
image

解决什么问题

ThreadLocal为每个线程提供了独立的变量副本来实现线程安全。
隔离性:每个线程都有自己的ThreadLocalMap,map的value只对当前线程可见,其他线程无法访问。
独立性:即使多个线程操作同一个ThreadLocal实例,但是每个线程都有自己的ThreadLocalMap,只不过key是同一个,最终操作的还是自己的副本。
场景:在web应用中,ThreadLocal常用语存储当前线程的用户信息,确保每个请求处理自己的数据。

最重要的API/动作

get方法

public T get() {  
	// 获取当前的线程
    Thread t = Thread.currentThread();  
	// 通过当前的线程获取ThreadLocalMap
    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();  
}

set方法

public void set(T value) { 
    Thread t = Thread.currentThread();  
    ThreadLocalMap map = getMap(t);  
    // 如果不为空插入k v
    if (map != null) {  
        map.set(this, value);  
    } else {  
	    // 如果是空创建ThreadLocalMap,并插入k v
        createMap(t, value);  
    }  
}

看下getMap方法和createMap方法,帮助理解上述的代码

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

remove()

public void remove() {  
    ThreadLocalMap m = getMap(Thread.currentThread());  
    if (m != null) {  
        m.remove(this);  
    }  
}
最大缺陷

当ThreadLocal使用完后被回收后,但是由于ThreadLocalMap是被线程持有,所以不会被回收,但是ThreadLocalMap中仍然存在null->value的引用,如果有长时间占用可能会发生内存泄漏。所以当使用完后手动remove确保资源释放。
remove方法会调用ThreadLocalMap的remove方法中的expungeStaleEntries方法,它会遍历删除key为null的entry。

posted on 2025-09-28 15:54  Ireck  阅读(5)  评论(0)    收藏  举报