ThreadLocal源码

ThreadLocal

  • 实际通过ThreadLocal创建的副本存储在每个线程自己的ThreadLocals中,ThreadLocal.ThreadLocalMap threadLocals = null;

  • 每个线程可以有多个threadLocals变量

  • 在get之前需要set,否则会有空指针异常

  • Entry是弱引用:保证ThreadLocal的生命周期与线程相同,方便GC

  • 通过线性探测法解决Hash冲突

  • 空间换时间的解决冲突办法

  • 用于数据库连接和Session管理

ThreadLocal.java

public class ThreadLocal {
    private final int threadLocalHashCode = nextHashCode();//标记不同的线程
    private static AtomicInteger nextHashCode =
        new AtomicInteger();
    
    public T get() {
        Thread t = Thread.currentThread();//获取当前线程
        ThreadLocalMap map = getMap(t);//获取当前线程对应的Map
        if (map != null) {//map不为空,返回value
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();//返回初始化值
    }
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;//返回当前线程t的threadLocals  
    }
    static class ThreadLocalMap {
        private Entry[] table;//使用数组存储各个线程的变量
        static class Entry extends WeakReference> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }
    }
    //不为空,设置键值对,为空直接创建map
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    //初始时,在Thread里面,threadLocals为空,
    //当通过ThreadLocal变量调用get()方法或者set()方法,
    //就会对Thread类中的threadLocals进行初始化,
    //并且以当前ThreadLocal变量为键值,
    //以ThreadLocal要保存的副本变量为value,存到threadLocals。
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    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源码)