Java源码分析-ThreadLocal

ThreadLocal提供了一个线程独立的变量。在不同线程中调set,get设置的值都是和该线程相关的。网上对ThreadLocal的实现众说纷纭,今天来看下源码。基于JDK1.8。

支持原创,转载请注明出处。

类图

Java源码分析-ThreadLocal_第1张图片
ThreadLocal.png

ThreadLocal.set方法

    public void set(T value) {
        Thread t = Thread.currentThread();   //获取当前线程对象
        ThreadLocalMap map = getMap(t);   //获取ThreadLocalMap对象
        if (map != null)
            map.set(this, value);               //调用ThreadLocalMap的set方法
        else
            createMap(t, value);
    }

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;              //返回Thread的ThreadLocalMap成员变量
    }

    ThreadLocal.ThreadLocalMap threadLocals = null;  //Thread的ThreadLocalMap成员

该方法获取当前线程的Thread对象中的trheadLocal成员变量,调用它的set方法。

ThreadLocalMap.set方法

        private void set(ThreadLocal key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);   //通过hash值,计算下标

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) { //不断获取下一个下标直到某个槽没有元素
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);             //将该元素加入这个槽
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

我们看下Entry这个类:

        static class Entry extends WeakReference> {
            /** The value associated with this ThreadLocal. */
            Object value;

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

这个类继承自WeakReference,所以只要ThreadLocal对象存在,那么设置在里面的值就不会被回收。我们看下get方法。

ThreadLocal.get方法

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

和set方法类似。我们看下map.getEntry方法:

       private Entry getEntry(ThreadLocal key) {
            int i = key.threadLocalHashCode & (table.length - 1); //计算下标
            Entry e = table[i]; 
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }

和set方法类似,一看就明白了。

总结

我们最后回顾下类图:

Java源码分析-ThreadLocal_第2张图片
ThreadLocal.png

支持原创,转载请注明出处。
github:https://github.com/gatsbydhn

你可能感兴趣的:(Java源码分析-ThreadLocal)