首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

谈谈你对 ThreadLocal 的理解

ThreadLocal 对有些同学来说可能有点陌生,今天我们就一起来学习一下。

What

ThreadLocal 直译就是「线程本地变量」,意思是 ThreadLocal 中填充的变量属于「当前」线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

How

ThreadLocal 最主要的作用就是线程隔离,在 Android 的消息机制中,很重要的一个角色 Looper,其中每个线程都要有自己的 Looper,这就是通过 ThreadLocal 实现的。直接看代码

用法也是相当的简单,变量最重要的无非就是 Setter 和 Getter . 这样我们就能在任意线程准备好自己的 Looper,也能获取到准备好的 Looper (线程内的单例)。

Why

接下来我们看下这么简单的接口,背后是怎么实现变量在线程间隔离的。

Setter

接下来我们来看下 ThreadLocalMap 又是什么

我们可以看到,这个 ThreadLocalMap 比 HashMap 的实现简单得多,只是简单的通过一个数组来保存 keyValue 的组合 entry,并且在 hash 值计算得出来的 Index 已经有数据时也仅需要简单的找下一个位置即可。另外这个 Hash 值的计算也是非常的简单:

小结一下:

每个 Thread 都有一个 ThreadLocalMap 里面存放了这个 Thread 的所有 ThreadLocal

这个 map 会在 ThreadLocal 设置值的时候去懒加载,再将 ThreadLocal 作为 key 要存的值作为 value 一起放入 map

通过 ThreadLocal 的 hash 值去确定需要 value 放在 Map 的哪个位置

Getter

有了前面的铺垫,我们再来看 Get 方法就轻松了很多

内存泄漏?

我们看到在 ThreadLocalMap.Entry 里,key 是 WeakReference

ThreadLocalMap 的 Setter / Getter 方法中就包含了一些清理已回收的 key 的逻辑

该 key 被回收时,这个 Thread 的生命周期可能也结束了,map 也一起回收了就无所谓泄露了

如果 Thread 生命周期较长,那么我们在使用完 ThreadLocal 时要主动调用 ThreadLocal.remove 方法,即可以在这个线程的 Map 移除对应的 Entry,从而避免泄露

总结

ThreadLocal 的作用是变量的线程隔离,同一个 ThreadLocal 在不同的线程中调用 get 方法会返回不同的 value

Thread 里有一个 ThreadLocalMap,用来存储本线程用到的 ThreadLocal 和 Value,每个线程都有自己的 ThreadLocalMap 就实现了变量线程隔离

ThreadLocalMap 本质上是用一个 Entry 数组来保存数据的,Entry 的 key 是 ThreadLocal 的弱引用,value 就是 ThreadLocal 对象 set 的值

ThreadLocalMap 里通过 ThreadLocal 的 hash 值来计算 Index, 当 index 冲突里继续找下一个可用的 index

ThreadLocal 有可能引起内存泄漏,确认使用结束可以调用 remove 移除相关引用

本文源码基于「Android-28」

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200825A043K100?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券