- 什么是ThreadLocal?
解决多线程并发时访问共享变量的问题,每个线程维护一个副本,互相之间隔离,但是同一线程不同方法和类之间共享 - 如何使用?
一般都会声明成一个静态变量
static ThreadLocal<Object> thread = new ThreadLocal<>();
常用方法:
set()
get()
remove()
原理:
ThreadLocal 内部有一个ThreadLocalMap对象,这个对象是一个Entry类型的数组,并且是弱引用,key是
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
// key为一个ThreadLocal对象,v就是我们要在线程之间隔离的对象
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
key是ThreadLocal本身,value是要存储的数据
探究一下几个方法的实现
- 拿到当前线程,当前线程作为参数,getMap方法拿到当前线程的threadLocals参数
这个threadLocals其实就是一个ThreadLocal.ThreadLocalMap对象, 最终拿到的就是每个线程内部的
ThreadLocalMap
![在这里插入图片描述](https://img-blog.csdnimg.cn/33b50c070dc54104befcecf453eeedac.png
ThreadLocal本身作为key,在set()方法内部,根据每个线程来计算不同的Entry数组的下标来存储,如图所,hashCode和长度-1做与运算类似于HashMap的寻址方式,减少哈希冲突
get()方法同理
remove()方法如图
- 内存泄露问题
很多人都说是弱引用导致的,其实不然
弱引用: 如果一个对象只有弱引用,下一次GC会回收
下图,使用强引用,ThreadLocalRef被回收,CurrentThreadRef没有回收,那么Entry存在强引用,ThreadLocal也不会被回收
弱引用:
ThreadLocal被回收了,Entry中会存在一个key位null,value不空的数组,造成内存泄漏,因此不管是强引用还是弱引用都会存在内存泄漏,每次使用完要调用remove(),手动清除
- ThreadLocal与Synchronized的区别
ThreadLocal其实是与线程绑定的一个变量。ThreadLocal和Synchonized都用于解决多线程并发访问。
但是ThreadLocal与synchronized有本质的区别:
1、Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
2、Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本
,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
- 简单使用