美文网首页
ThreadLocal简析

ThreadLocal简析

作者: MadnessXiong | 来源:发表于2020-04-29 22:25 被阅读0次

    1. ThreadLocal简介

    顾名思义,ThreadLocal的功能就是为每一个使用局部变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他的线程副本冲突。从线程的角度讲,就好像每一个线程都完全拥有该变量。

    2. ThreadLocal源码简析

    2.1 ThreadLocal如何维护变量

    既然ThreadLocal让每一个线程都拥有自己的变量,那么就需要维护此变量,在ThreadLocal类中,有一个内部类ThreadLocal.ThreadLocalMap来负责此工作:

    static class ThreadLocalMap {   
                    /**
                    * 定义一个弱引用Entry类,用来保存ThreadLocal和value之间的关系
                    * 之所以用弱引用,是为了解决线程与ThreadLocal之间的强绑定关系,如果线程没有被回收,GC也可以回收这个对            * 象
                    */
            static class Entry extends WeakReference<ThreadLocal<?>> {
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
        }
    

    ThreadLocalMap内部通过一个Entry来保存ThreadLocal和value之间的关系,Entry是一个弱引用,用来防止内存泄漏

    2.2 ThreadLocal的set():

        public void set(T value) {
            //获取当前线程
            Thread t = Thread.currentThread();
            //根据当前线程获取ThreadLocalMap
            ThreadLocalMap map = getMap(t);
            if (map != null)
                //存储
                map.set(this, value);
            else
                createMap(t, value);
        }
            //创建一个ThreadLocalMap
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
            //获取ThreadLocalMap
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
        }
    

    首先看createMap(),在这个方法中,构造了一个ThreadLocalMap,将ThreadLocal本身和要绑定的变量传入,然后将构造好的ThreadLocalMap赋值给了当前线程t,也就是说当前线程t持有了ThreadLocalMap对象。而这个ThreadLocalMap对象绑定了当前ThreadLocal和变量,形成了Thread->ThreadLocal->变量之间的绑定关系。

    再看set()本身,首先获取当前线程t,根据当前线程t去获取当前的ThreadLocalMap,上面说过,当前线程t持有了当前ThreadLocalMap。所以假如ThreadLocalMap已创建,是可以获取到的。如果没创建就去创建。如果创建了就调用ThreadLocalMap.set()将当前ThreadLocal和变量绑定。

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

    get()中首先获取了当前线程t,然后通过getMap(),获取了当前线程的ThreadLocalMap,然后再通过map.getEntry(this),传入当前ThreadLocal取出与之绑定的变量。

    相关文章

      网友评论

          本文标题:ThreadLocal简析

          本文链接:https://www.haomeiwen.com/subject/svpowhtx.html