1、什么是ThreadLocal
ThreadLocal提供线程内的局部变量,不同的线程之间不会相互干扰,这种变量在线程的生命周期内起作用,减少同一个线程内或组件之间一些公共变量传递的复杂度。
2、如何使用
ThreadLocal的方法主要就是set(),get(),remove(),没啥好说的。
看一下线程不隔离导致读取了本不该属于它的数据。
当使用ThreadLocal将变量与当前线程绑定:
3、实现原理
3.1 set()
set方法也就是把数据放入ThreadLocalMap中
而ThreadLocalMap的实现是通过Entry数组
可以看出,当前ThreadLocal
的引用k被传递给WeakReference
的构造函数,所以ThreadLocalMap
中的key
为ThreadLocal
的弱引用。当一个线程调用ThreadLocal
的set方法设置变量的时候,当前线程的ThreadLocalMap
就会存放一个记录,这个记录的key
值为ThreadLocal
的弱引用,value
就是通过set设置的值。如果当前线程一直存在且没有调用该ThreadLocal
的remove
方法,如果这个时候别的地方还有对ThreadLocal
的引用,那么当前线程中的ThreadLocalMap
中会存在对ThreadLocal
变量的引用和value对象的引用,是不会释放的,就会造成内存泄漏。
3.2 get()
在get
方法的实现中,首先获取当前调用者线程,如果当前线程的threadLocals
不为null,就直接返回当前线程绑定的本地变量值,否则执行setInitialValue
方法初始化threadLocals
变量。
在setInitialValue
方法中,类似于set
方法的实现,都是判断当前线程的threadLocals
变量是否为null,是则添加本地变量(这个时候由于是初始化,所以添加的值为null),否则创建threadLocals
变量,同样添加的值为null。
3.3 remove()
remove
方法判断该当前线程对应的threadLocals
变量是否为null,不为null就直接删除当前线程中指定的threadLocals
变量。
4、扩展
- 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象 ;
- 软引用:在使用软引用时,如果内存的空间足够,软引用指向的对象就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用指向的对象才会被垃圾回收器回收;
- 弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用指向的对象回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象 。
- 虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。