当前位置:网站首页>浅谈ThreadLocal和InheritableThreadLocal,源码解析
浅谈ThreadLocal和InheritableThreadLocal,源码解析
2022-06-23 07:05:00 【追风中的小少年】
浅谈ThreadLocal和InheritableThreadLocal
ThreadLocal浅谈
首先有个概念可以提供大家参考:threadLocal只是操作thread类中threadLocalMap变量的一个工具,理解了这个对大家理解下边文章有好处
1,ThreadLocal的创建
一般创建一个ThreadLocal对象ThreadLocal threadLocal = new ThreadLocal<>()生成一个ThreadLocal对象,
2,ThreadLocal的set方法源码
当对该对象进行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);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
流程为,获取当前执行线程 Thread t = Thread.currentThread();
getMap方法中获取当前线程的线程变量 t.threadLocals,
而threadLocals 是Thread类型的变量 ThreadLocal.ThreadLocalMap
ThreadLocalMap属于ThreadLocal中的内部类,是一个Entry数组,
第一次创建的ThreadLocal的ThreadLocal.ThreadLocalMap threadLocals = null;默认是null;
所以第一次的set方法会执行createMap(t, value);方法
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
createMap是生成了一个ThreadLocalMap对象并赋值给当前线程变量threadLocals,
到这里ThreadLocal的set方法执行完毕。
3,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();
}
get源码是比较简单的,在获取到当前线程的ThreadLocalMap之后去获取ThreadLocalMap中entry中存储的值,
比较有意思的是这个setInitialValue()方法;
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);
return value;
}
当生成threadLocal未进行set操作之前进行get操作,会执行这个setInitialValue()方法,会创建一个key值为this,value为null的数据放入当前线程的threadLocalMap中
3,ThreadLocal的remove方法源码
remove源码更为简单,做了当前threadLocalMap的清空工作
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
至此ThreadLocal的基本源码就阅读完成了
InheritableThreadLocal浅谈
InheritableThreadLocal为ThreadLocal的子类,复写了ThreadLocal的单个方法
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
/** * Computes the child's initial value for this inheritable thread-local * variable as a function of the parent's value at the time the child * thread is created. This method is called from within the parent * thread before the child is started. * <p> * This method merely returns its input argument, and should be overridden * if a different behavior is desired. * * @param parentValue the parent thread's value * @return the child thread's initial value */
protected T childValue(T parentValue) {
return parentValue;
}
/** * Get the map associated with a ThreadLocal. * * @param t the current thread */
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
/** * Create the map associated with a ThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the table. */
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
1,InheritableThreadLocal和ThreadLocal的区别和联系
InheritableThreadLocal可以实现父子线程变量的共享,而ThreadLocal变量不能在其子线程中获取,
2,InheritableThreadLocal是如何实现父字线程变量共享的
当我们创建一个子线程时,执行了Thread类型以下源码
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
****省略的代码
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
可以看到最后一个init方法中,也就是Thread类第418行到420的代码
有一个将当前线程inheritableThreadLocals的复制搬运动作,来完成了父子线程间的通讯
那么为什么inheritableThreadLocals会不为null呢,因为InheritableThreadLocal复写了ThreadLocal的getMap方法,返回了Thread变量中的inheritableThreadLocals实现初始化
ThreadLocal用法举例
1,例如做一些oa系统,可能会涉及在代码中获取当前登录人的信息,可以通过ThreadLocal去做一些当前登录人信息的记录
2,接口耗时的日志记录也可以记录用ThreadLocal做一些记录动作
边栏推荐
猜你喜欢

yolov5检测小目标(附源码)

User mode and kernel mode

基于51单片机的温度检测监测报警系统设计
![[veusz] import 2D data in CSV](/img/22/467139f5a83ce9e88a57ced732d4d6.png)
[veusz] import 2D data in CSV

Sstable details

一篇文章学会er图绘制

微信多人聊天及轮盘小游戏(websocket实现)
![[deep learning] [original] how to detect targets and draw map and other parameter maps without yolov5 weights or models](/img/f3/ff14cb5439a24e26f977e5f0d15785.png)
[deep learning] [original] how to detect targets and draw map and other parameter maps without yolov5 weights or models

Abnormal logic reasoning problem of Huawei software test written test

Friends of the week
随机推荐
codeforce 158B Taxi
快手350014
Elaborate on the operation of idea
1278_FreeRTOS_借助prvAddCurrentTaskToDelayedList接口理解delayed task
Detailed explanation of redis persistence, master-slave and sentry architecture
Sstable details
Using the for loop to output an alphabetic triangle
leetcode210. Schedule II 207 Curriculum topology sorting DFS BFS
[AI practice] xgb Xgbregression multioutputregressor parameter 2 (GPU training model)
MySQL on duplicate key and PgSQL on conflict (primary key) handle primary key conflicts
U-Net: Convolutional Networks for Biomedical Image Segmentation
[AI practice] data normalization and standardization of machine learning data processing
Heuristic search strategy
NTU-RGBD数据集下载及数据格式解析
Spock sub piling
Unity picture loading and saving
基于51单片机的温度检测监测报警系统设计
Feelm joined the Carbon Disclosure Project as an initiative of Smallville to deal with climate change emergencies
MySQL transaction isolation level
跳跃表原理