ThreadLocal的源码分析

首先是Thread类的源码:

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal源码:

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();
    }
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代码进行set和get时,实际上是对一个ThreadLocalMap进行操作,
而这个ThreadLocalMap对象是使用当前线程对象传递给getMap方法得到的一个map对象。而getMap方法是怎么拿到当前线程的ThreadLocalMap对象呢?
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

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

首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。


总结:ThreadLocal对象 实际上是对当前线程的ThreadLocalMap对象引用的一个封装(副本),ThreadLocal对象的set和get方法,实质上是对当前线程对象的ThreadLocalMap的set和get方法。

你可能感兴趣的:(Java基础)