threadlocal原理_ThreadLocal初体验

这篇博客介绍了ThreadLocal在Java中的作用,它提供线程内的局部变量,避免参数传递。通过示例展示了ThreadLocal如何在不同线程间保持变量隔离,并解释了其内部get、set和remove方法的工作原理。文章强调每个线程有自己的threadLocals存储变量,key为ThreadLocal实例,value为变量,简化了多层方法间的参数传递。
摘要由CSDN通过智能技术生成

前些日子遇到一个需求,要在消息列表对之前版本的做消息详情的兼容,做兼容很简单,无非就是获取版本号做一个不同的实现。但是恶心的是需要把这个版本号一层一层的从方法里传递进来,其实看之前所有的兼容,都是在最初的方法中后续增加appVersion来实现兼容功能,那有没有什么办法可以实现不通过传递参数也能获取到版本号呢?直到遇到了threadLocal

——什么是ThreadLocal?

jdk中是这么解释的

9707edad5b1b3f928ff63196ab67042e.png

意思大概是ThreadLocal提供线程内的局部变量,这些变量在多线程访问时能保证各个线程中的变量相对独立于于其他线程中的变量。ThreadLocal实例通常来说是private static类型的,用来关联线程和线程的上下文。

总结一下呢,就是它提供线程内的局部变量,在本线程里即取即用,可以减少函数里公共变量传递的复杂度。

——举个

既然把threadLocal写的这么神奇,我们不妨来试一试吧

首先我们先定义一个threadLocal,并给予初始值

cf8446d64a558729a4a2fb823049bd5f.png

之后我们定义线程,并对这些线程进行加法操作

1325d2d67a631334cc8b7432402b765e.png

输出结果

d96ea5bb3cf65b932a98666c56de9e32.png

从结果中我们可以看到,各个线程之间的值时相互隔离的

——原理

那threadLocal的内部实现是怎么样的呢?

这里我们要了解一下threadLocal的三个方法,也是我们主要用到的三个方法:

public T get()

get方法:获取当前threadLocal的值,如果没有则返回默认值

public void set(T value)

set 方法:用来设置当前threadLocal的值

public void remove()

remove方法:用来删除当前threadLocal的值

我们来看看get方法

aa40e3f7448dcf179aedec2f9a2a9c47.png

首先获取当前线程,再通过当前线程获取threadLocalMap

84c00134379519cfebc4a32673d3789a.png

在getMap方法中,我们发现获取到的是当前线程的一个成员变量threadsLocals

d1aa371426693d2864f53ac6814178c6.png

这个threadLocals其实就是threadLocalMap,是threadLocal的一个内部类

594388812dfd7e139bb2e2d1c6ba3ea5.png

而在threadLocalMap中,我们可以看到,它继承了弱引用,用treadLocal作为key,用户需要传递的副本变量作为value

继续来看setInitialValue方法

f4db0d7681ee359c8eaf4bb661de75e9.png

很直观的可以看到,当map不为空时,设置键值对,当value为空时,则去新建一个map

d30dfc24fe60299ca2476535cd449027.png

其实从一个get方法中,我们就大概明白了threadLocal的原理

每个线程都有一个 threadLocal.threadLocalMap 类型的成员变量threadLocals,这个threadLocals就是用来存储我们需要传递的变量,key为当前的threadLocal,value为变量;

开始时,用set方法对thread中的threadLocals初始化,当前hreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals;当需要使用时,就可以通过get方法获取到变量,当然这个前提是在同一个线程中。

——小结

注意,划重点啦!~

1.每个threadLocal创建的变量其实是存储在每个线程自己的threadLocals中

2.为什么要用threadLocal作为key而不用每个线程的id呢?因为一个线程中是可以有多个threadLocal的,如果用线程id作为key,那就不知道如何区分放进threadLocals的value啦

3.在没有重写setInitValue前提下,要先set再get,默认的值为null会导致空指针哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值