ThreadLocal其实也很简单

it2025-04-25  30

ThreadLocal两大使用场景
每个线程都需要一个独享的对象(一般是工具类,如SimpleDateFormat和Random)每个线程内需要保存全局变量,(拦截器获取用户信息)可以让不同方法直接使用,避免参数传递麻烦,同一个线程不同方法共享
ThreadLocal两个作用
让某个需要用到的对象在线程间隔离(每个线程都有自己的独立对象)在任何方法中都可以轻松获取到该对象
ThreadLocal带来的好处
达到线程安全不需要加锁,提高执行效率更高效地利用内存、节省开销
Thread、ThreadLocal、ThreadLocalMap三者的关系

ThreadLocalMap是Thread类的一个成员变量,所以一个Thread对应了一个ThreadLocalMap。一个ThreadLocalMap里面可以多个以ThreadLocal对象为key的键值对。

ThreadLocal常用方法

threadLocal.get()方法

public T get() { //1、先获取当前线程 Thread t = Thread.currentThread(); //2、获取该线程的ThreadLocalMap对象 ThreadLocalMap map = getMap(t); if (map != null) { //3、根据当前threadLocal对象为key去获取值 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //如果改线程的ThreadLocalMap为空就会去setInitialValue()方法中获取initialValue()中默认的值,如果不重写该方法则返回null return setInitialValue(); } //setInitialValue()方法源码如下: private T setInitialValue() { //initialValue()没重写默认return null T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { map.set(this, value); } else { createMap(t, value); } if (this instanceof TerminatingThreadLocal) { TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this); } return value; }

threadLocal.set(T 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); } }

threadLocal.remove()

public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) { m.remove(this); } }
ThreadLocal带来的问题
内存泄漏:就是某个对象不再有用了,但是其占用的内存却不能被回收了。ThreadLocal造成内存泄漏的原因是,ThreadLocalMap的每一个Entry的key为弱引用而值为强引用。 static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { //k为WeakReference弱引用 super(k); value = v; } } 正常情况下,当线程终止时,ThreadLocal里的value会被正常回收。但是当线程长时间不终止(如在线程池中),因为key是弱引用就可以被回收,而value则不能被回收。链路为Thread->ThreadLocalMap->Entry(key为null)->Value,value和Thread和Thread之间还有强引用链路,所以导致value无法回收,就可能出现OOM;如何避免内存泄漏:使用ThreadLocal完后调用remove()方法。
最新回复(0)