当前位置:网站首页>浅谈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做一些记录动作
边栏推荐
- G++ compilation command use
- Product axure9 (English version), prototype design and production pull-down secondary menu
- 快速删除代码里面的node_modules
- 1278_FreeRTOS_借助prvAddCurrentTaskToDelayedList接口理解delayed task
- Basic experiment of data statistics and analysis - basic grammar and operation
- Nacos adapts to oracle11g- modify the source code of Nacos
- HCIP之路
- The road to hcip MPLS
- YGG 西班牙 subDAO——Ola GG 正式成立
- Online text filter less than specified length tool
猜你喜欢

Eureka服务注册与发现

Yan's DP analysis

Ntu-rgbd data set download and data format analysis

1278_FreeRTOS_借助prvAddCurrentTaskToDelayedList接口理解delayed task

How MySQL converts a date to a number

在线文本过滤小于指定长度工具

How flannel works

如何优雅的快速下载谷歌云盘的大文件 (二)

Friends of the week

Detailed explanation of redis persistence, master-slave and sentry architecture
随机推荐
Ntu-rgbd data set download and data format analysis
codeforce 158B Taxi
Unity图片加载和保存
What is customer experience automation?
Wechat multiplayer chat and Roulette Games (websocket Implementation)
WPS for thesis writing installs MathType plug-in to write mathematical formulas
Test APK exception control nettraffic attacker development
. H5 file forgets the database name and uses h5py to print
【Kubernetes】Kubernetes各大版本的最新版本下载地址
NFS 特别注意权限的问题
[AI practice] xgb Xgbregression multioutputregressor parameter 2 (GPU training model)
MySQL (11) - sorting out MySQL interview questions
Principle of skip table
C WPF additional attribute implementation interface defines decorator
[AI practice] xgb Xgbregression multioutputregressor parameter 1
Focusing on the industry, enabling customers | release of solutions for the five industries of the cloud container cloud product family
EXCEL VBA 入门与实用例子
在线JSON转CSharp(C#)Class工具
Data types in tensorflow
【PyQt5系列】修改计数器实现控制