ThreadLocal 源码分析

ThreadLocal 源码分析

set方法

public void set(T value) {
// 获取当前线程对象即key
Thread t = Thread.currentThread();
// 获取当前线程的ThreadLocal.ThreadLocalMap
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
// 将key,value放入map中
map.set(this, value);
} else {
// 创建map
this.createMap(t, value);
}

}

getMap方法–获取当前线程的ThreadLocal.ThreadLocalMap

ThreadLocal.ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
在这里插入图片描述

set方法–将key,value放入map中

private void set(ThreadLocal<?> key, Object value) { ThreadLocal.ThreadLocalMap.Entry[] tab = this.table; int len = tab.length; // 做与运算计算value下标 int i = key.threadLocalHashCode & len - 1; // 通过开放寻址法找到tab中位置并放入 for(ThreadLocal.ThreadLocalMap.Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = (ThreadLocal)e.get();
// key相等覆盖当前Entry的值
if (k == key) {
e.value = value;
return;
}
// 将强引用转换为弱引用,并且将之前出现过数据冲突的数据做数据搬移
if (k == null) {
this.replaceStaleEntry(key, value, i);
return;
}
}
// 直接放入key,value
tab[i] = new ThreadLocal.ThreadLocalMap.Entry(key, value);
int sz = ++this.size;
// 将以当前位置以后的数据做数据搬移,超过负载因子rehash
if (!this.cleanSomeSlots(i, sz) && sz >= this.threshold) {
this.rehash();
}

    }

replaceStaleEntry方法

private void replaceStaleEntry(ThreadLocal<?> key, Object value, int staleSlot) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;
int slotToExpunge = staleSlot;

ThreadLocal.ThreadLocalMap.Entry e;
int i;

// 以当前位置为起始位置,向前找,找到第一个key为null,但entry不为null
for(i = prevIndex(staleSlot, len); (e = tab[i]) != null; i = prevIndex(i, len)) {
if (e.get() == null) {
slotToExpunge = i;
}
}
// 将当前位置以及后面的数据做一个置null操作然后数据搬移
for(i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
ThreadLocal<?> k = (ThreadLocal)e.get();
if (k == key) {
e.value = value;
tab[i] = tab[staleSlot];
tab[staleSlot] = e;
if (slotToExpunge == staleSlot) {
slotToExpunge = i;
}

        this.cleanSomeSlots(this.expungeStaleEntry(slotToExpunge), len);
        return;
    }

    if (k == null && slotToExpunge == staleSlot) {
        slotToExpunge = i;
    }
}

tab[staleSlot].value = null;
tab[staleSlot] = new ThreadLocal.ThreadLocalMap.Entry(key, value);

// 清理向前为key null value不为null的,数据搬移
if (slotToExpunge != staleSlot) {
this.cleanSomeSlots(this.expungeStaleEntry(slotToExpunge), len); }

}

expungeStaleEntry方法

rehash数据搬移

private int expungeStaleEntry(int staleSlot) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;
tab[staleSlot].value = null;
tab[staleSlot] = null;
–this.size;

ThreadLocal.ThreadLocalMap.Entry e;
int i;
for(i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
    ThreadLocal<?> k = (ThreadLocal)e.get();
    if (k == null) {
        e.value = null;
        tab[i] = null;
        --this.size;
    } else {
        int h = k.threadLocalHashCode & len - 1;
        if (h != i) {
            for(tab[i] = null; tab[h] != null; h = nextIndex(h, len)) {
            }

            tab[h] = e;
        }
    }
}

return i;

}

cleanSomeSlots方法

将值的强引用转换为弱引用
private boolean cleanSomeSlots(int i, int n) {
boolean removed = false;
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;
int len = tab.length;

do {
    i = nextIndex(i, len);
    ThreadLocal.ThreadLocalMap.Entry e = tab[i];
    if (e != null && e.get() == null) {
        n = len;
        removed = true;
        i = this.expungeStaleEntry(i);
    }
} while((n >>>= 1) != 0);

return removed;

}

createMap方法

hash槽创建
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
}

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
this.table = new ThreadLocal.ThreadLocalMap.Entry[16];
int i = firstKey.threadLocalHashCode & 15;
this.table[i] = new ThreadLocal.ThreadLocalMap.Entry(firstKey, firstValue);
this.size = 1;
this.setThreshold(16);
}

get方法

public T get() {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
ThreadLocal.ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = e.value;
return result;
}
}

return this.setInitialValue();

}

getEntry方法

private ThreadLocal.ThreadLocalMap.Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & this.table.length - 1;
ThreadLocal.ThreadLocalMap.Entry e = this.table[i];
return e != null && e.get() == key ? e : this.getEntryAfterMiss(key, i, e);
}

getEntryAfterMiss方法

private ThreadLocal.ThreadLocalMap.Entry getEntryAfterMiss(ThreadLocal<?> key, int i, ThreadLocal.ThreadLocalMap.Entry e) {
ThreadLocal.ThreadLocalMap.Entry[] tab = this.table;

for(int len = tab.length; e != null; e = tab[i]) {
    ThreadLocal<?> k = (ThreadLocal)e.get();
    if (k == key) {
        return e;
    }

    if (k == null) {
// 数据搬移
        this.expungeStaleEntry(i);
    } else {
        i = nextIndex(i, len);
    }
}

return null;

}

setInitialValue方法

private T setInitialValue() {
T value = this.initialValue();
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
map.set(this, value);
} else {
this.createMap(t, value);
}

if (this instanceof TerminatingThreadLocal) {
    TerminatingThreadLocal.register((TerminatingThreadLocal)this);
}

return value;

}

inheritableThreadLocals是使得子线程可以从父线程中得到值的设计的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值