ThreadLocal
ThreadLocal 是Java中 lang 包下的一个类,是用来解决多线程下共享变量并发问题的,所谓共享变量即同一个变量在不同线程下赋予不同值, 而ThreadLocal会在不同线程中维护共享变量的独立副本
Categories:
前置 线程池
是 Java 中提供的一种用于实现线程局部变量的工具类。它允许每个线程都拥有自己的独立副本,从而实现线程隔离,用于解决多线程中共享对象的线程安全问题。
使用:
创建 ThreadLocal对象
//创建一个ThreadLocal变量
public static ThreadLocal<String> localVariable = new ThreadLocal<>();
设置值
//设置ThreadLocal变量的值 localVariable.set("0001");
获取值
//获取ThreadLocal变量的值 String value = localVariable.get();
优点
-
线程隔离 实现了变量的独占, 使变量不需要同步处理
-
数据传递方便 ThreadLocal 常用于在跨方法、跨类时传递上下文数据(如用户信息等),而不需要在方法间传递参数。
ThreadLocalMap
ThreadLocalMap, 一个key-value数据形式结构,也是ThreadLocal的核心。
Map内部维护了一个Entry数组, 真正的数据存储在 Entry中, map的key是每个线程中ThreadLocal对象的哈希, value是隔离变量
/**
* 初始容量
*/
private static final int INITIAL_CAPACITY = 16;
/**
* ThreadLocalMap数据真正存储在table中
*/
private Entry[] table;
/**
* ThreadLocalMap条数
*/
private int size = 0;
/**
* 达到这个大小,则扩容
*/
private int threshold; // 默认为0
为了保证Entry[] 数组散步均匀, 哈希算法如下
把对应的 key 映射到 table 数组的相应下标,ThreadLocalMap 用的是哈希取余法,取出 key 的 threadLocalHashCode,然后和 table 数组长度减一&运算(相当于取余)。
int i = key.threadLocalHashCode & (table.length - 1);
这里的hashcode由魔术数生成
每创建一个 ThreadLocal 对象,它就会新增0x61c88647
,这个值很特殊,它是斐波那契数 也叫 黄金分割数。hash
增量为 这个数字,带来的好处就是 hash
分布非常均匀。
InheritableThreadLocal()
父子线程是无法传输数据的, 但是通过InheritableThreadLocal实例就可以在子线程拿到值
public class InheritableThreadLocalTest {
public static void main(String[] args) {
final ThreadLocal threadLocal = new InheritableThreadLocal();
// 主线程
threadLocal.set("父线程");
//子线程
Thread t = new Thread() {
@Override
public void run() {
super.run();
System.out.println("子线程 ," + threadLocal.get());
}
};
t.start();
}
}
原理:
在Thread中有一个变量
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
在 Thread.init 的时候,如果父线程的inheritableThreadLocals
不为空,就把它赋给当前线程(子线程)的inheritableThreadLocals
。