多线程之ThreadLocal
最近学习多线程相关的东西,今天搞一搞ThreadLocal
简介
ThreadLocal叫做线程变量,线程对于ThreadLocal的set与get的变量,只属于当前线程,对于其他线程是隔离的
public static void main(String[] args) {ThreadLocal<String> threadLocal = new ThreadLocal<>();for (int j = 0; j < 3; j++) {new Thread(() -> {threadLocal.set(Thread.currentThread().getName());System.out.println(Thread.currentThread().getName() + ":" + threadLocal.get());}).start();}System.out.println("======================================");threadLocal.remove();}
当前线程设置什么,get出来就是什么,完全和其他线程无关
ThreadLocal的作用:
1.使每个线程都有自己独立的对象,例如当并发状态下,多个不同用户访问系统时,单个线程的用户信息对象set到ThreadLocal之后,在这个线程内,用户的信息始终一致
2.解决了参数传递的麻烦,同一个线程内, 在任何方法中都可以轻松获取到本线程对应set 的对象
ThreadLocal的实现原理:
浅看源码,ThreadLocal内部维护了一个ThreadLocalMap,而ThreadLocalMap内部则是Entry数组,当set时或者get时,使用当前线程作为key,再通过key计算出value应该在Entry数组的下标位置
以get为例,走一下代码执行过程
首先拿到当前线程对象,用当前线程获取ThreadLocalMap,如果map不为null,则以当前线程(this)为key获取Entry对象 key.threadLocalHashCode & (table.length - 1)则是计算key对应value在数组中的位置
如果在get()之前没有set,那么会走setInitialValue()方法,创建map,并且将线程作为key,null作为value返回
这就是一次大概的过程,set和remove也差不多,都是对于Map的操作,可以拿着上面的main方法跑一下,点开ThreadLocal源码读一读马上就豁然开朗了,几个方法的开头都是先获取当前线程,因此与其他线程完全隔离
ThreadLocal数据结构示意,图片来源于网络
ThreadLocal的一些问题:
在使用完之后万无一失的处理是对ThreadLocal进行remove处理,否则可能会出现内存泄漏问题,因为我们在开发过程中,很多时候线程池中优先使用的都是核心线程,这样的话栈中线程引用不会被回收,那么对应的entry对象的数据也会一直存在,堆栈引用关系后面专门再聊一聊
上一篇 >>>>> 记录错误Transaction was marked for rollback only; cannot commit