ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java源码阅读之深入理解ThreadLocal

2019-03-31 17:48:15  阅读:301  来源: 互联网

标签:map java Thread ThreadLocalMap value ThreadLocal 源码 Entry


总结:每一个Thread实例中都会保存一个map数据结构,其中用来存储Thread实例用到的每个ThreadLocal的哈希值和其对应的value。使用set和get方法时,利用ThreadLocalHashCode在Thread实例的map中查找和修改其value值。

先看简介

ThreadLocals rely on per-thread linear-probe hash maps attached to each thread (Thread.threadLocals and inheritableThreadLocals). The ThreadLocal objects act as keys, searched via threadLocalHashCode.

  • 本地线程们依赖挂载到每个线程上的哈希表maps。本地线程对象为key,通过threadLocalHashCode搜索。

从初始化函数切入

    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);
        }
        if (this instanceof TerminatingThreadLocal) {
            TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
        }
        return value;
    }
  • 我们可以看到使用了ThreadLocalMap这个对象,其为ThreadLocal的内部静态类,阅读后得知其中有Entry类为弱引用(防止垃圾回收无法回收Entry对象)
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
  • 继续阅读初始化函数,通过getMap获取map对象
    ThreadLocal.ThreadLocalMap threadLocals = null;
  • 每一个Thread对象都保存了一个map用来保存ThreadLocal和value副本,如果map为null则在Thread的map中添加一个新的Entry对象(稍后会解释)
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
  • 注意:创建map中新的Entry<key,value>对象的key不是Thread实例的hashcode而是ThreadLocalHashCode
  • 这样每个Thread通过维持一个map数据结构就拥有其所有的ThreadLocal中的变量副本了

Set方法

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }
  • 依旧从Thread实例中获取map,如果没有该变量则在map中新建一个Entry<ThreadLocalHashCode, value>,如果有的话就修改

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();
    }
  • 如果map不为空则获取LocalThreadMap中的Entry对象,以ThreadLocalHashCode在map中匹配value,如果map为空则重新进行初始化

标签:map,java,Thread,ThreadLocalMap,value,ThreadLocal,源码,Entry
来源: https://blog.csdn.net/weixin_42072543/article/details/88930877

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有