既然ThreadLocal是给每个线程都创建一份变量副本,而这些变量副本之间互不关联,那么为什么不直接在本线程创建变量?还有一个问题,“副本”这个说法是不是本身就不太准确,每个线程都会自行单独的设置值,这些值本身是谁的“副本”,主线程吗?
既然ThreadLocal是给每个线程都创建一份变量副本,而这些变量副本之间互不关联,那么为什么不直接在本线程创建变量?还有一个问题,“副本”这个说法是不是本身就不太准确,每个线程都会自行单独的设置值,这些值本身是谁的“副本”,主线程吗?
如果能够用完即扔,线程隔离当然是个更好的方式,而且还没有状态,绝对不会对其他线程产生影响。但线程的生民周期超长,如果不能统一管理变量,很容易就内存泄漏了,针对编码来说,就更加困难。其实你使用ThreadLocal
,它依然时使用的 Thread.threadLocals
这也是一个 Map
,是和线程绑定的
。和你说的也没差,从某种意义上来说,它使用的依然是线程隔离
技术,而且还额外提供了更强大
的功能。至于副本一说,我是有点摸不着头脑,ThreadLocal
只有在使用的时候会为thread
创建一个ThreadLocalMap,这一点对thread 增加了额外的负担
,只能在线程退出
时才能清理。但它的key
是用的软引用,而且每次操作都会检查 陈旧项目
,已经尽可能的把负担降到最低,一般的程序员也写不出这么好的代码。
结合@weak_ptr 的答案看一下。
前端用户点击按钮,调用controller,后续经过一系列的调用栈,执行完毕后返回到前台。
这个周期是一个线程的生命周期。
如果你想在这一系列的调用栈里随时获取用户信息,在调用controller里你可以通过session,但是在service层是获取不到的。如果你想在这一个线程的生命周期内随便取用用户信息,要么你就得每个方法传几十个形参,要么你就用一个全局变量。同时你还不能让这个全局变量让别的线程改了,那么你就需要一个线程内的全局变量,这就是ThreadLocal。
为什么不直接在本线程创建变量
请问如何创建线程内的全局变量?
静态变量是全局的,不是线程有效的。所以pass。
通过传参给每个方法??
定义个map<线程id,变量值>??这不就是ThreadLocal嘛。
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答6k 阅读
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
一点个人见解。
1,你说“那么为什么不直接在本线程创建变量?”
没错的,如果你需要的只是一个局部变量,那就写个局部变量就行,不用太考虑 ThreadLocal。
ThreadLocal 应对的场景是你想要让所有线程用相同的方式访问,而又不互相影响。比如这个爆栈的回答就比较好。
像是我们写 web 应用的时候,有很多数据是和请求/会话绑定的,比如当前请求的用户信息,来源,请求数据,你可以在每个调用里传这些参数(也就是你说的,我可以写一个局部变量来实现):
又或者,稍微灵活一点,不用在请求绑定的数据出现变化时动函数签名,也不用改 request 或者别的什么类的字段,只要把所有和请求绑定的数据都存进 ThreadLocal 就好了。
很多时候 ThreadLocal 并不是非他不可,只是另一种可能更漂亮、实用的选择。
2,还有一个问题,“副本”这个说法是不是本身就不太准确,每个线程都会自行单独的设置值,这些值本身是谁的“副本”,主线程吗?
本质上,ThreadLocal 就是个 Map<线程ID,你的数据>,‘副本’这个词表达的是每个线程都有自己的数据,这是站在全局的角度(每个线程都有自己的数据)而不是单个线程的角度(我读写我的数据)看的。
所以‘副本’不能理解为‘是某个对象的复制品’,更像是‘一个线程一个坑’。