一、前言
物欲横流的信息时代下,性能和效率是产品在百花齐放中脱颖而出的致胜法宝。作为软件研发人员,在物理硬件固定的情形中,如何确保程序高效吞吐赫然是必备的看家本领。而提升效率就会涉及老生常谈的多线程处理,那么对于这种高效手段需要注意的线程安全问题,相比很多猿友一定耳濡目染了,今天帝都的雁为大家带来一种线程安全的技术手--ThreadLocal。(PS:需要有JVM垃圾回收、强引用、软引用、弱引用以及虚引用等相关理论基础)
二、用法
ThreadLocal<T> threadLocal = new ThreadLocal<>();
在程序中我们直接创建ThreadLocal即可。
ThreadLocal常用的API如下:threadLocal.set(T t);
T t = threadLocal.get();
threadLocal.remove();
细心的猿友会发现ThreadLocal的使用有点类似于map,真的是这样吗?
三、源码解读
1、set(T value)
2、getMap(Thread t)
3、ThreadLocalMap
4、get()
5、remove()
看完源码后,感觉还是比较简单的,你是否会有疑问:为什么要去使用ThreadLocal呢?或者它有哪些优点值得我们学习使用?
四、线程安全的特性
由于ThreadLocal在每个线程中都存放了副本数据,所以线程内部处理这些数据时,天然线程隔离,彼此互不干扰,是一种典型的空间换取时间的高效处理方式。
不同于synchronized,synchronized是采用同步阻塞的方式进行时间换取空间,在高并发下,惨不忍睹的效率局限了其使用范围。
五、使用场景
ThreadLocal在很多主流框架中都进行了应用。
1、Spring的声明式事务
2、Pagehelper分页插件
3、SpringMVC的请求链我们自己也可以广泛地去使用它,比如:当我们接口传递参数较多时,多个接口之间不想重复去写这么多参数名称,既冗余又逼格低,我们可以采用ThreadLocal去将这些参数放入此次请求的线程中,使用时从线程中获取出来。
六、内存泄漏问题
这是ThreadLocal使用上需要特别注意的地方。
何为内存泄漏?对象使用结束,且不会被再次使用到,那么这个对象实际上就是一个垃圾,需要被垃圾回收器进行回收,但如果因为某种原因导致本该回收的垃圾对象,无法被回收掉。这时,就出现了内存泄漏。久而久之,堆内存持久增长,最终导致内存溢出。
为什么ThreadLocal就会出现内存泄漏呢?由源码可看出Entry继承了弱引用。那么,我们就先来看看引用的类型吧。
1、强引用
直接指向对象的引用,如Object o1 = new Object(); Object o2 = o1;
这时o1和o2都是强引用,即使发生垃圾回收,也不会被回收掉。
2、软引用
堆内存不足,进行垃圾回收时,软引用指向的对象会被回收掉。
3、弱引用
WeakReference,只要进行垃圾回收,弱引用指向的对象一定会被回收掉。
4、虚引用
虚引用执行的对象随时都会被回收掉,常用于记录对象存活状态。
故此,我们可以得出:ThreadLocal在ThreadLocalMap中以弱引用的方式存放数据。当有垃圾回收时,ThreadLocal执行的对象就会被垃圾回收器收集,释放占用内存,使得其原本的<ThreadLocal, Value>变为<null, Value>。这个Entry永远不会被再次使用到了,但却由于其存放在线程的ThreadLocalMap中,导致其无法被垃圾回收器收集,从而发生内存泄漏。
所以,我们在使用ThreadLocal时,尽量使用之后使用其remove方法手动删除,避免内存泄漏。
七、垃圾回收机制
JAVA优于其它语言的特性之一在于,无需研发者手动是否对象的内存空间,交由JAVA自身的垃圾回收机制去收回这些不再使用的对象内存。那么,垃圾回收是怎么触发的呢?
首先,我们需要明确JVM的内存结构。按照线程独占和线程共享可大致分为如下:
1、线程独占
栈:存放引用地址,由一个个栈帧组成,栈帧中又由本地变量表、操作数栈、动态连接和返回地址组成。
本地方法栈:存放与C语言进行通讯的接口。
程序计数器:记录当前线程执行至哪一行代码。
2、线程共享
堆:存放创建出来的对象。
元空间(静态方法区):存放class的相关信息、静态信息等
在对JAVA内存结构有了一定轮廓后,就需要分析垃圾回收机制的原理。我们知道,堆内存是存放创建出来的对象,那么当堆内存满了的话,有程序再去申请内存空间,就会发生内存溢出的异常OutOfMemory(简称:OOM)。JAVA为了减少这种异常,人性化的设置了垃圾回收机制,当堆内存的对象成为垃圾时,会被垃圾回收器回收掉内存。而垃圾回收器判断对象是否要被回收的依据就是对象是否可达(与堆内存外的数据地址有联系),然后依照自身的机制去做对应算法分析后,进行垃圾处理。
欢迎大家和帝都的雁积极互动,头脑交流会比个人埋头苦学更有效!共勉!
公众号:帝都的雁