天翼云代理,天翼云代理商,北京代理商
天翼云2.5折专线:18510009100/18510009200(全国市话)

聊聊Java中的ThreadLocal作用

2022-04-02 03:12:48

在java中,如果我们多线程操作变量的时候,需要加上同步控制机制,原因是多线程操作一个变量,那么如果每个线程都操作自己线程的变量,那就不用加锁了,也不用加同步控制了。

ThreadLocal就是这个作用,比如在Web开发中,我们用ThreadLocal来保存用户信息,然后传递后台多个service,然后每个线程单独获取自己的用户信息;

初始化代码也比较简单:

使用比较简单,通过重载initialValue()这个方法进行初始化,或通过set进行设置,然后get使用即可,整个使用过程类似于HashMap。

那如何神奇的控制不同的线程保存不同的数据,从而达到线程的共享那,如下:

首先代码中通过Thread.currentThread()来获取当前的线程id,通过线程id获取对应的ThreadLocalMap,这个getMap,其实是获取Thread的成员变量如下:

此成员变量定义如下:

然后再来看这句话:

即通过本ThreadLocal的对象作为key,获取Entry对象后,再获取它的value,如果为null那,那就调用setInitialValue()进行初始化,代码如下:

此线程的map如果存在,不为null,直接更新,返回默认的初始化值,即initialValue()的返回值,如果不存在,则调用createMap(t,value);来创建map,如下:

说实话代码挺绕的,找了网上一张图,会形成如下的结构:

【图来自互联网,侵权删除】

我们从这个图可以看到,ThreadLocal是所有线程的map的公共key,还要注意到,这个map比较特殊,是内部自己实现的,通过线性探测的方法来解决哈希冲突的,即如果槽位已经被占用了,则通过一个函数计算得到下一个槽位, 这种方法解决冲突的效率比较低,所以不建议用太多的ThreadLocal变量。

Threadlocal相关的数据结构:

【图片来自互联网,侵权删除】

【图片来自互联网,侵权删除】

从上图中可以看到Entry继承自弱应用,下次gc的时候会回收,但是只有key是弱引用,value还是强引用,下次gc的时候,key被回收而value可能一直不会被回收。

所以解决办法是,使用过之后记得通过remove()进行删除。

总结:

ThreadLocal适用于无状态的线程内变量共享的场景,比如我们说的通过ThreadLocal保存每个线程特有的信息,比如线程标识(打日志的时候适用,便于排查问题)。

ThreadLocal有一定的内存泄漏分享,记得要remove。

12年经验 · 提供上云保障

服务热线:132-6161-6125(手机) 400-150-1900(全国市话)

站内导航: 天翼云服务器价格| 天翼云购买流程| 天翼云代理| 北京天翼云代理商| 杭州天翼云代理| 深圳天翼云代理商| 钉钉代理商| 阿里云代理| 公司官网

我公司收款账号| 天翼云备案系统

CopyRight © 2019 天翼云代理商. All Rights Reserved 京ICP备2024071855号-7 管理-北京优胜智连科技有限公司