写点什么

ThreadLocal 源码分析 - 扩容和 get 方法

作者:zarmnosaj
  • 2022-10-19
    四川
  • 本文字数:1279 字

    阅读完需:约 1 分钟

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();    }
复制代码


Thread t = Thread.currentThread(); get 获取之前,从获取当前的线程对象,因为 ThreadLocal 保存的数据也都是属于当前线程的


getMap(t); 从当前线程中获取 ThreadLocalMap 对象


ThreadLocalMap.Entry e = map.getEntry(this); 从 ThreadLocalMap 中获取 entry,entry 中保存的就是具体的值


在 ThreadLocalMap 的 getEntry 方法中,方法内部首先是将参数的 hash 值与数组大小取模并减一,作为索引位置查询数据,如果找不到对应的数据(数据为空)则自选将索引+1 继续寻找,直到找到为止。因为这种不断的自旋找法,如果使用了大量的 key 的话,数据获取的效率就会很低。

扩容方法

        private void resize() {            Entry[] oldTab = table;            int oldLen = oldTab.length;            int newLen = oldLen * 2;            Entry[] newTab = new Entry[newLen];            int count = 0;
for (int j = 0; j < oldLen; ++j) { Entry e = oldTab[j]; if (e != null) { ThreadLocal<?> k = e.get(); if (k == null) { e.value = null; // Help the GC } else { int h = k.threadLocalHashCode & (newLen - 1); while (newTab[h] != null) h = nextIndex(h, newLen); newTab[h] = e; count++; } } }
setThreshold(newLen); size = count; table = newTab; }
复制代码


Entry[] oldTab = table; 先拿出旧的数组


int newLen = oldLen * 2; 扩容的新数组为旧数组大小的 2 倍


for (int j = 0; j < oldLen; ++j) { ... } 将老数组的值拷贝到新数组中


setThreshold(newLen); 设置数组新的扩容阈值,阈值为数组长度的三分之二


这里的扩容不像 ArrayList 或者其他线程安全的集合扩容方法,这里没有考虑 modCount,也就是没有考虑到线程不安全的情况,这是因为本来这就是线程的独属的方法,只有一个线程,也就是线程本身才能操作这部分的数据,所以不会存在线程不安全的情况。

总结

ThreadLocals.ThreadLocalMap 和 InheritableThreadLocals.ThreadLocalMap 是线程独有的属性,每个线程的 ThreadLocal 都是隔离的,所以是线程安全的。


当在一个线程中创建另一个线程时,也就存在父子线程的关系,但是子线程的 ThreadLocal 不会和父线程的 ThreadLocal 共享。

发布于: 刚刚阅读数: 3
用户头像

zarmnosaj

关注

靡不有初,鲜克有终 2020-02-06 加入

成都后端混子

评论

发布
暂无评论
ThreadLocal 源码分析-扩容和get方法_10月月更_zarmnosaj_InfoQ写作社区