这篇文章主要介绍“Inheritable中的ThreadLocal是什么”,在日常操作中,相信很多人在Inheritable中的ThreadLocal是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Inheritable中的ThreadLocal是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
1、简介 在上一篇 ThreadLocal详解 中,我们详细介绍了ThreadLocal原理及设计,从源码层面上分析了ThreadLocal。但由于ThreadLocal设计之初就是为了绑定当前线程,如果希望当前线程的ThreadLocal能够被子线程使用,实现方式就会相当困难(需要用户自己在代码中传递)。在此背景下,InheritableThreadLocal应运而生。
Inheritable thread-local variables are used in preference to ordinary thread-local variables when the per-thread-attribute being maintained in the variable (e.g., User ID, Transaction ID) must be automatically transmitted to any child threads that are created.
2、应用 调用链追踪:在调用链系统设计中,为了优化系统运行速度,会使用多线程编程,为了保证调用链ID能够自然的在多线程间传递,需要考虑ThreadLocal传递问题(大多数系统会使用线程池技术,这已经不仅仅是InheritableThreadLocal能够解决的了,我会在另外一篇文章中介绍相关技术实现)。
3、InheritableThreadLocal类 InheritableThreadLocal类重写了ThreadLocal的3个函数:
`/** * 该函数在父线程创建子线程,向子线程复制InheritableThreadLocal变量时使用 */ protected T childValue(T parentValue) { return parentValue; } /** * 由于重写了getMap,操作InheritableThreadLocal时, * 将只影响Thread类中的inheritableThreadLocals变量, * 与threadLocals变量不再有关系 */ ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * 类似于getMap,操作InheritableThreadLocal时, * 将只影响Thread类中的inheritableThreadLocals变量, * 与threadLocals变量不再有关系 */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); }`
注意:由于重写了getMap()和createMap()两个函数,所以当
4、线程间传值实现原理 说到InheritableThreadLocal,还要从Thread类说起:
public class Thread implements Runnable { ......(其他源码) /* * 当前线程的ThreadLocalMap,主要存储该线程自身的ThreadLocal */ ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal,自父线程集成而来的ThreadLocalMap, * 主要用于父子线程间ThreadLocal变量的传递 * 本文主要讨论的就是这个ThreadLocalMap */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; ......(其他源码)
}`
Thread类中包含 threadLocals 和 inheritableThreadLocals 两个变量,其中 inheritableThreadLocals 即主要存储可自动向子线程中传递的ThreadLocal.ThreadLocalMap。 接下来看一下父线程创建子线程的流程,我们从最简单的方式说起:
4.1、用户创建Thread, Thread thread = new Thread();
4.2、Thread创建
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
4.3、Thread初始化
/** * 默认情况下,设置inheritThreadLocals可传递 */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } /** * 初始化一个线程. * 此函数有两处调用, * 1、上面的 init(),不传AccessControlContext,inheritThreadLocals=true * 2、传递AccessControlContext,inheritThreadLocals=false */ private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { ......(其他代码) if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); ......(其他代码) }`
可以看到,采用默认方式产生子线程时,inheritThreadLocals=true;若此时父线程inheritableThreadLocals不为空,则将父线程inheritableThreadLocals传递至子线程。
4.4、ThreadLocal.createInheritedMap 让我们继续追踪createInheritedMap:
`static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } /** * 构建一个包含所有parentMap中Inheritable ThreadLocals的ThreadLocalMap * 该函数只被 createInheritedMap() 调用. */ private ThreadLocalMap(ThreadLocalMap parentMap) { Entry[] parentTable = parentMap.table; int len = parentTable.length; setThreshold(len); // ThreadLocalMap 使用 Entry[] table 存储ThreadLocal table = new Entry[len]; // 逐一复制 parentMap 的记录 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) { // 可能会有同学好奇此处为何使用childValue,而不是直接赋值, // 毕竟childValue内部也是直接将e.value返回; // 个人理解,主要为了减轻阅读代码的难度 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++; } } } }`
从ThreadLocalMap可知,子线程将parentMap中的所有记录逐一复制至自身线程。
5、总结 InheritableThreadLocal主要用于子线程创建时,需要自动继承父线程的ThreadLocal变量,方便必要信息的进一步传递。
到此,关于“Inheritable中的ThreadLocal是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。