五、面试必问知识点——ThreadLocal实现、原理、示例

203 阅读1分钟

7、ThreadLocal底层实现

   每个Thread都有一个ThreadLocalMap对象,ThreadLocalMap持有对象的引用,
   该对象跟当前线程绑定,ThreadLocalMap以当前的threadLocal对象为key,
   以ThreadLocal里面存的值为value。保存一份变量的副本,副本保存在线程中的,
   而不是保存在ThreadLocal变量中;从而实现线程之间的数据的隔离

8、 ThreadLocal源码:

1)、set()方法:
        public void set(T value) {
        //获取当前线程对象
        Thread t = Thread.currentThread();
        //获取当前线程对象的ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null)
            //以当前threadLocal对象为key,实际存储对象为value
            map.set(this, value);
        else
            createMap(t, value);
        }
        //获取Thread类中的ThreadLocalMap对象
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
        }
        //创建Thread类中的ThreadLocalMap成员对象
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
        //初始化ThreadLocalMap对象
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            //INITIAL_CAPACITY初始值为16
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
        //初始化加载因子
        private void setThreshold(int len) {
            threshold = len * 2 / 3;
        }

2)、get()方法:
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                //threadlocal实例为key获取到对应Entry,然后从Entry中取出对象
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            //map为空时,设定初始值
            return setInitialValue();
        }
        
        private T setInitialValue() {
            T value = initialValue();
            //同set方法一样
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        }
        
        protected T initialValue() {
            return null;
        }
3)、remove()方法:
        public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
        }

9、ThreadLocal使用场景(JDBC的连接、管理会话HttpSession等)

如图: