java中ThreadLocal和ThreadLocalMap浅析
ThreadLocal和ThreadLocalMap
先发一个最常见的图

关键字 ThreadLocal ThreadLocalMap Thread
1 概念 ThreadLocal

理解:ThreadLocal类用来设置线程私有变量 本身不储存值 主要提供自身引用 和 操作ThreadLocalMap 属性值得方法,使用ThreadLocal会通过ThreadLocal的引用定位到到堆中Thread的类ThreadLocalMap里散列表里的值 从而达到线程私有
目的:解决多线程使用共享对象的问题 空间换时间
2 存储形式
ThreadLocalMap(ThreadLocal 的静态内部类 由ThreadLocal类来维护和创建)中
a:和普通Hashmap类似存储在一个数组内,但与hashmap使用的拉链法解决散列冲突的是 ThreadLocalMap使用开放地址法 //开放地址法缺点 : -空间利用率低 开发地址发会在散列冲突时寻找下一个可存入的槽点 为了避免冲突 负载因子会设置的相对较小 还使用的原因是 ThreadLocalMap的散列值均匀 且经常增删 纯数组较方便 节点数量少 时也能节省掉指针域带来的空间开销
b : 数组 初始容量16,负载因子2/3
c : node节点 的key封装了WeakReference 用于回收
d : 数组位置计算
ThreadLocalMap属性
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
//初始容量16
private static final int INITIAL_CAPACITY = 16;
//散列表
private Entry[] table;
//entry 有效数量
private int size = 0;
//负载因子
private int threshold; ThreadLocalMap设置ThreadLocal 变量
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
//与运算 & (len-1) 这就是为什么 要求数组len 要求2的n次幂
//因为len减一后最后一个bit是1 与运算计算出来的数值下标 能保证全覆盖
//否者数组有效位会减半
//如果是hashmap 计算完下标后 会增加链表 或红黑树的查找计算量
int i = key.threadLocalHashCode & (len-1);
// 从下标位置开始向后循环搜索 不会死循环 有扩容因子 必定有空余槽点
for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
//一种情况 是当前引用 返回值
if (k == key) {
e.value = value;
return;
}
//槽点被GC掉 重设状态
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
//槽点为空 设置value
tab[i] = new Entry(key, value);
//设置ThreadLocal数量
int sz = ++size;
//没有可清理的槽点 并且数量大于负载因子 rehash
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}3 储存位置
储存在Thread中的两个ThreadLocalMap变量

4 储存时机
threadLocals 在ThreadLocal对象方法get中去创建 也由ThreadLocal来维护
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
**createMap**(t, value);
}
void createMap(Thread t, T firstValue) {
t.threadLocals = **new ThreadLocalMap**(this, firstValue);
}inheritableThreadLocals 和ThreadLocal类似 InheritableThreadLocal重写了createMap方法
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}inheritableThreadLocals 作用是将ThreadLocalMap传递给子线程

init方法中 条件满足后直接为子线程创建ThreadLocalMap

重要
a: 仅在初始化子线程的时候会传递 中途改变副线程的inheritableThreadLocals 变量 不会将影响结果传递到子线程 。
b:使用线程池要注意 线程不回收 尽量避免使用父线程的inheritableThreadLocals 导致错误
到此这篇关于java中ThreadLocal和ThreadLocalMap浅析的文章就介绍到这了,更多相关ThreadLocal和ThreadLocalMap内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解SpringBoot中5种类型参数传递和json数据传参的操作
当涉及到参数传递时,Spring Boot遵循HTTP协议,并支持多种参数传递方式,这些参数传递方式可以根据请求的不同部分进行分类,2023-12-12
深入分析Comparable与Comparator及Clonable三个Java接口
接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义,这篇文章主要为大家详细介绍了Java的Comparable,Comparator和Cloneable的接口,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助2022-05-05
Java was started but returned exit code=13问题解决案例详解
这篇文章主要介绍了Java was started but returned exit code=13问题解决案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下2021-09-09


最新评论