ThreadLocal (二):什么时候使用 InheritableThreadLocal
一、ThreadLocal 在父子线程传递的问题
public class InheritableThreadLocalDemo {
// 全局变量
// static ThreadLocal<String> threadLocal = new ThreadLocal<>();
static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
InheritableThreadLocalDemo.threadLocal.set("superWorld");
new Service().call();
}
}).start();
}
}
class Service {
public void call() {
System.out.println("Service:" + Thread.currentThread().getName() + " : " + InheritableThreadLocalDemo.threadLocal.get());
//new Dao().call();
new Thread(new Runnable() {
@Override
public void run() {
new Dao().call();
}
}).start();
}
}
class Dao {
public void call() {
System.out.println("Dao:" + Thread.currentThread().getName() + " : " + InheritableThreadLocalDemo.threadLocal.get());
}
}
二、InheritableThreadLocal 和 ThreadLocal 的区别
1. InheritableThreadLocal 实现
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);
}
}
2. ThreadLocal 的getMap、createMap实现
/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
} /**
* Create the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @param firstValue value for the initial entry of the map
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
通过上面的代码我们可以看到InheritableThreadLocal 重写了childValue, getMap,createMap三个方法,
当我们往里面set值的时候,值保存到了inheritableThreadLocals里面,而不是之前的threadLocals。
三、问题:为什么当创建子线程时,可以获取到上个线程里的threadLocal中的值呢?
原因就是在新创建线程的时候,会把之前线程的inheritableThreadLocals赋值给新线程的inheritableThreadLocals,通过这种方式实现了数据的传递。
代码关键点:
1. Thread#init
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
2. ThreadLocal.createInheritedMap
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
private ThreadLocalMap(ThreadLocalMap parentMap) {
Entry[] parentTable = parentMap.table;
int len = parentTable.length;
setThreshold(len);
table = new Entry[len];
for (int j = 0; j < len; j++) {
Entry e = parentTable[j];
if (e != null) {
@SuppressWarnings("unchecked")
ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
if (key != null) {
Object value = key.childValue(e.value);
Entry c = new Entry(key, value);
int h = key.threadLocalHashCode & (len - 1);
while (table[h] != null)
h = nextIndex(h, len);
table[h] = c;
size++;
}
}
}
}
ThreadLocal (二):什么时候使用 InheritableThreadLocal的更多相关文章
- 理解ThreadLocal(二)
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...
- 彻底理解ThreadLocal二
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...
- 深入理解ThreadLocal(二)
3 InheritableThreadLocal的使用 通过上面的分析知道通过ThreadLocal保存的值是线程隔离的.其实在Thread对象中,还有一个ThreadLocal.ThreadLoca ...
- 【并发编程】ThreadLocal的兄弟InheritableThreadLocal
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 引子 public class InheritableT ...
- java多线程系类:JUC线程池:03之线程池原理(二)(转)
概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包 ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- 【Java】深入理解ThreadLocal
一.前言 要理解ThreadLocal,首先必须理解线程安全.线程可以看做是一个具有一定独立功能的处理过程,它是比进程更细度的单位.当程序以单线程运行的时候,我们不需要考虑线程安全.然而当一个进程中包 ...
- ThreadLocal源码分析-黄金分割数的使用
前提 最近接触到的一个项目要兼容新老系统,最终采用了ThreadLocal(实际上用的是InheritableThreadLocal)用于在子线程获取父线程中共享的变量.问题是解决了,但是后来发现对T ...
- java中threadlocal的理解
[TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...
随机推荐
- 正则化--L1正则化(稀疏性正则化)
稀疏矢量通常包含许多维度.创建特征组合会导致包含更多维度.由于使用此类高维度特征矢量,因此模型可能会非常庞大,并且需要大量的 RAM. 在高维度稀疏矢量中,最好尽可能使权重正好降至 0.正好为 0 的 ...
- C语言学习笔记(二) 基础知识
数据类型 C语言数据可以分为两大类: 基本类型数据和复合类型数据: 基本类型数据 整数 整型 (int) ——占4字节 短整型(short int) ——占2字节 长整型(long in ...
- cassandra的primary key, partition key, cluster key,
https://stackoverflow.com/questions/24949676/difference-between-partition-key-composite-key-and-clus ...
- Ireport常用操作汇总
1.四则运算 new java.lang.Double(($F{fincome}.doubleValue())/($F{fhomePopulation}.intValue()))
- 执行”spark-shell –master yarn –deploy-mode client”,虚拟内存大小溢出,报错
在Hadoop 2.7.2集群下执行如下命令: spark-shell --master yarn --deploy-mode client 爆出下面的错误: org.apache.spark.Sp ...
- Notes from Data Guard
There are two types of Standby databases: 1, Physical standby database block-for-block basis the phy ...
- Atitit.android jsbridge v1新特性
Atitit.android jsbridge v1新特性 1. Java代码调用js并传参其实是通过WebView的loadUrl方法去调用的.只是参数url的写法不一样而已1 2. 三.JAVA ...
- Angularjs学习笔记11_手工初始化
http://my.oschina.net/fuckBAT/blog/375579 Angular的编译机制允许开发人员给浏览器添加新的Html语法,允许我们添加一些html节点,attribute, ...
- undefined reference to `shm_unlink'
1.问题描述: 在编译一个程序的时候提示这样的错误: BLog.cpp:(.text+0x5fc): undefined reference to `shm_unlink'DBLog.cpp:(.te ...
- 推荐vim配置
"设置编码,处理中文乱码,文件默认utf8编码set fileencodings=utf-8,ucs-bom,cp936,big5 "设置默认配色方案colorscheme def ...