Java ThreadLocal原理与源码
来源:互联网 发布:用一套好还是用淘宝好 编辑:程序博客网 时间:2024/04/29 14:28
1. 开始
Java中的ThreadLocal类很有意思,它提供了一种线程中的局部变量机制。这种变量与一般的变量不同,一般的变量是在多线程环境中(通过get或set方法)拷贝一份副本,而threadlocal变量是独立的线程内部拷贝。一般,ThreadLocal的实例常常用作private static类型,用于关联一个线程和线程上下文。ThreadLocal内部提供了一个ThreadLocalMap,用于保存local局部变量。创建ThreadLocal时,会先创建ThreadLocalMap, 而创建ThreadLocalMap是以当前的ThreadLocal对象为key,local变量为值,最后ThreadLocalMap会绑定到当前线程内部中的threadLocals。因此获取local 变量时,是直接获取当前线程内部中的ThreadLocalMap。由于线程在JVM中是独立调度的,每个线程都有自己的上下文,因此内部的变量都是独立的。概括言之:ThreadLocal提供线程内部的局部变量,在本线程中随用随取,隔离其他线程。
2. 用代码说明
JDK中的源码说明中,提供了一个示例,看看设计者是怎么理解与使用的。
public class UniqueThreadIdGenerator { private static final AtomicInteger uniqueId = new AtomicInteger(0); private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return uniqueId.getAndIncrement(); } } /** Returns the current thread's unique ID, assigning it if necessary */ public static int get() { return threadId.get(); public static void main(String[] args) { int id = get(); System.out.println("CID: " + id); }}
新建ThreadLocal 变量时,可以直接覆盖initialValue()方法,用于初始化一个预设值,也可以调用set()方法在后期运行中设定值。想要获取绑定在线程中的变量的值时,直接调用get()方法即可。
3. 源码分析
1. 先分析在创建ThreadLocal变量时,覆写了initialValue方法的场景。
直接瞅瞅get()方法
源码上的注释为:返回当前thread-local变量在当前线程中的副本,如果这个变量在当前线程中还没有值,则将返回其在初始化方法中设定的初始值。
public T get() { Thread t = Thread.currentThread(); //获取当前线程 ThreadLocalMap map = getMap(t); //获取当前线程内部的threadlocalmap副本 if (map != null) { //第一次调用时,map返回为空 ThreadLocalMap.Entry e =map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); //map为空,因此调用设定初始化方法}ThreadLocalMap getMap(Threadt) { return t.threadLocals; //线程内部中的threadlocalmap} private T setInitialValue() { T value = initialValue(); //运行时,调用实际覆写的方法,返回初始值 Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) //在本场景中,map仍然为空 map.set(this, value); else createMap(t, value); //map为空,则创建map return value; //返回设定的初始值} voidcreateMap(Thread t, T firstValue) { //以当前的ThreadLocal对象为key,初始值为value,并绑定到当前线程中,赋值给当前线程中的threadLocals,下次获取时即不为空 t.threadLocals = newThreadLocalMap(this, firstValue);}
因此,调用get方法时的流程简要如下:
2. 再来看看直接调用set方法的场景。
类似的,也是从当前线程中获取到threadlocalmap,如果不为空则设置值,如果为空则创建map,然后再设置值。
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
4. 还有InheritableThreadLocal
InheritableThreadLocal 接继承自ThreadLocal. 使用InheritableThreadLocal,子线程便可以继承父线程中的所有的Local变量值。接继承自ThreadLocal. 使用InheritableThreadLocal,子线程便可以继承父线程中的所有的Local变量值。
创建InheritableThreadLocal时,会覆盖createMap方法,并关联到线程Thread中的inheritableThreadLocals属性。
使用时直接实例InheritableThreadLocal即可,如:
InheritableThreadLocal inheritableLocal= new InheritableThreadLocal();
在执行创建ThreadLocalMap时会调用子类的createMap方法,其方法如下:void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);}
创建子线程时,从当前线程实例化一个thread时,其中的一段代码为:
if(parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
子线程会可以获取到父线程中ThreadLocalMap,因此继承父线程中的所有local变量值。
- Java ThreadLocal原理与源码
- ThreadLocal原理与源码分析
- 【惊天真相】ThreadLocal原理与源码分析
- java.lang.ThreadLocal实现原理和源码分析
- ThreadLocal原理与应用
- ThreadLocal原理与应用
- ThreadLocal原理与用法
- threadLocal 原理与使用
- 源码|ThreadLocal的实现原理
- [Java并发] ThreadLocal原理
- java-----ThreadLocal源码分析
- Java 源码解析-ThreadLocal
- Java ThreadLocal源码分析
- ThreadLocal用法与实现原理
- ThreadLocal的使用与原理
- ThreadLocal与WeakReference 源码分析
- ThreadLocal与ThreadLocalMap源码解析
- 【Java多线程】ThreadLocal实现原理
- 2016关键词
- Python图像处理库PIL的ImageFont模块介绍
- 算法代码实现之归并排序,C/C++实现,自顶向下与自底向上两种方式
- Java正则表达式
- 《Linux内核分析》第一周 理解计算机是如何工作的
- Java ThreadLocal原理与源码
- windows下ffmpeg录制摄像头内容
- 《现代操作系统》读书笔记
- 基于51单片机的稳压电压
- 百度地图图片叠加层切片工具:制作边界透明覆盖物
- gradle与gradle wrapper关系,以及版本关系
- 通过登录窗口调用主窗口的办法、禁止线程多开
- 不让苹果开发者账号折磨我
- 顺序容器操作2 在顺序容器中添加元素