ThreadLocal类提供线程局部变量。这些变量和其他普通的变量的区别在于,每个线程获取的线程局部变量都拥有自己相对独立的初始化过的副本。ThreadLocal的实例通常被声明为private static 来希望达到关联线程的状态的目的(例如:userId,transaction id)。
按我本人的理解有两点注意:
第一:ThreadLocal提供的线程局部变量通常都是新new的。这个他们都是初始一样的,最后和线程关联的,相对独立的。
第二:ThreadLocal是为了解决线程内部数据共享,而不是为了解决线程间数据共享(synchronized).将同一个引用分别放到不同线程的threadLoca变量中,一个改变,都改变。
看一下ThreadLocal的成员变量
private final int threadLocalHashCode = nextHashCode(); private static AtomicInteger nextHashCode = new AtomicInteger(); private static final int HASH_INCREMENT = 0x61c88647; private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); }
每个threadLocal有一个threadLocalHashCode变量,每个ThreadLocal实例的threadLocalHashCode值都是不一样的,每次都是在上次的基础上增加HASH_INCREMENT。至于为什么是这个数,主要是为了解决
冲突问题,这个特殊的hash值是定制化的。
ThreadLocal对象的重要方法解析
先看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; } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
ThreadLocal调用set的过程就是:获取当前线程对象的ThreadLocalMap变量,如果存在就以ThreadLocal实例为key,传入的值为value存入ThreadLocalMap变量。如果不存在就new一个ThreadLocalMap对象,并且赋给当前线程对象。
再看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(); } 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; }
get的过程是:获取当前线程实例的ThreadLocalMap变量,它是一个map,之前存的时候是以threadlocal对象作为key的,现在先试图通过这个key(也就是this),获取ThreadLocalMap.Entry类型的值。如果获取不为空,返回value,如果为空,说明之前没有存,这个时候调用setInitialValue()。这个方法调用initialValue()方法,初始化value,以ThreadLocal对象为key(也就是this), value为值,初始化ThreadLocalMap,并返回value.
再看一下ThreadLocal对象的remove方法
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
remove的过程就是调用ThreadLocalMap的remove方法,移除以threadlocal为key的值。
至此,我们发现,调用ThreadLocal的方法,其实内部是调用本线程实例对象(Thread)的ThreadLocalMap成员变量的想关方法实现的.因此,ThreadLocalMap才是理解线程局部变量的关键。
相关推荐
ThreadLocal源码分析,主要有ThreadLocal源码以及ThreadLocal的内部结构在jdk8前后的变化
ThreadLocal_ThreadLocal源码分析_源码.zip
ThreadLocal源码分析和使用
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
java并发包源码分析(3)ThreadLocal 详细配图讲解 java并发包源码分析(3)ThreadLocal 详细配图讲解
ThreadLocal 线程微本地变量 及 源码分析
ThreadLocal的原理,源码深度分析及使用.docx,这是一份ThreadLocal的技术文档
主要给大家介绍了关于Java并发编程学习之源码分析ThreadLocal的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
一、简介 ThreadLocal是JDK包提供的,它提供了线程本地变量,也就是如果你创建了一个ThreadLocal变量,那么访问这个变量的每一个线程都会有这个变量的一个本地副本。...根据源码,画出ThreadLocal原理图 原创文章
分析都是基于android sdk 23 源码进行的,ThreadLocal在android和jdk中的实现可能并不一致。 在最初使用Threadlocal的时候,很容易会产生的误解就是threadlocal就是一个线程。 首先来看下Threadlocal的简单...
NULL 博文链接:https://liuinsect.iteye.com/blog/1827012
NULL 博文链接:https://gerrard-ok.iteye.com/blog/1851903
activiti源码分析,详细介绍工作流的基础框架和一些源码
5、Condition源码分析 6、ReentrantReadWriteLock底层实现原理 7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、ThreadLocal 为什么会内存泄漏 10、Volatile...
接着通过一个简单的应用场景,为该 Web 应用添加若干业务功能,从需求分析与系统设计开始,带领读者动手完成该 Web 应用,完善相关细节,并对已有代码进行优化;然后基于传统 Servlet 框架搭建一款轻量级 Java Web ...
java并发编程总结,包括多线程安全机制分析总结,Unsafe源码分析总结,并发工具类总结,ThreadLocal原理和使用,Fork/Join框架使用总结,同步容器和并发容器源码分析
JDK1.8源码分析 相关的原始码分析结果会以注解的形式体现到原始码中 已完成部分: ReentrantLock CountDownLatch Semaphore HashMap TreeMap LinkedHashMap ConcurrentHashMap 执行器 ...
高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4 高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4 高并发编程第三阶段13讲 一个JNI程序的编写,通过...
高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4 高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4 高并发编程第三阶段13讲 一个JNI程序的编写,通过...
源码分析concurrent包 ConcurrentHashMap CopyOnWriteArrayList BlockingQeque ThreadLocal 反射 Kotlin Kotlin的优势 协程 Android热门技术 代码插桩技术 动态代理 插件化 热修复 日志系统 OKHttp Jetpack LiveData...