IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> ThreadLocal 原理分析 -> 正文阅读

[大数据]ThreadLocal 原理分析

Android 的消息机制 Looper 的实现就采用了 ThreadLocal ,使用 ThreadLocal 可以实现数据隔离,那它是怎么实现的呢?现在来分析一波,先看它的 set() 流程。

一、set(T value) 流程分析

image.png

在这里,通过调用 ThreadLocal 的 set 方法,这里很简单,只有简单的几个步骤:

  • 获取调用这个方法的线程。
  • 获取 ThreadLocalMap,并且对 map 进行判空处理。

其实? ThreadLocalMap 就类似与 HashMap ,使用的是 key-value 的映射,这里可以暂先这样理解,后面会慢慢分析,接下来看 get 的流程。

二、get() 流程分析

image.png

这里话同样是先获取到了当前的线程和 ThreadLocalMap ,然后对 map 进行判断处理。先看 map 为空的处理:

image.png

感觉是不是和 set 流程似曾相识。在这里,如果 get? 没有获取到元素或者 map 为空的话,就会走进这个流程里面。initialValue() 实际上返回了 null,也就是说,如果 get? 没有获取到元素或者 map 为空的话,会创建 map 并且返回 null。

接下来看 map 不为空的流程:

image.png

这里的话很好理解,先通过 key 的hashcode 和 数组长度 - 1 进行 &? 运算获取 value 对应的索引值,然后通过索引值获取value 。

三、ThreadLocalMap

之前说过 ThreadLocalMap 是一个基于 key-value 的映射,那么这里的 key 和 value 分别是什么呢?通过之前的我分析可以看到,value 的ThreadLocal 所引用的泛型类,而这里的 key,其实就是这个 ThreadLocal 变量。

每一个线程都有一个 ThreadLocalMap,key 对应着这个 ThreadLocal 变量,value 对应着这个 T 类型的对象,接下来继续对set 流程进行分析。

之前对 ThreadLocal? 的 set 方法进行了简单的分析,它会对 map 进行判空处理,如果获取的 map 为空,最终会走到下面的这个方法里面来:

image.png

在这里,可以分成以下几个步骤:

  • 创建一个 table 数组。
  • 获取索引值,获取方式之前讲过了。
  • 在这个索引所在的位置,创建一个节点。
  • 设置阈值,注意这里不是数组长度的 0.75,而是 三分之二。

接下来看 map 不为空的流程:

image.png

在这个可以看到,通过这个 key 拿到了索引之后,就会顺着这个索引的位置往下寻找,直到找到一个索引位置不存在节点的位置,然后在这个位置,使用 value 创建一个新的节点,之后才会判断是否需要扩容。

可以看到,这里的 set 的非常简单,如果发生了哈希冲突,就采用线性探测的方法,而不是像 HashMap 那样采用了链表 +? 红黑树的数据结构。

四、内存泄漏的分析

ThreadLocal 为什么会发生内存泄漏呢?我们来看看 ThreadLocalMap 中 Entry 节点的相关代码:

image.png

可以看到这个 Entry 节点继承自 WeakReference,构造方法中对 key 进行了弱引用的处理,但是value依然是强引用,现在问题就来了。如果这个 key 没有被外部对象强引用的时候,就会在发生 GC 的时候被回收掉,但是它对应的 value 不会被回收,如果创建 ThreadLocal 的线程一直运行下去 Entry 对象对应的 value 就会一直得不到回收,从而发生内存泄漏。

解决的方法很简单,我们需要手动调用 remove 方法。


作者:JonesYong
链接:https://juejin.cn/post/7005850803978108959
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 10:55:57  更:2021-09-10 10:56:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:49:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码