ThreadLocal源码分析

ThreadLocal

是什么?

首先,咱们从名字上来看就是线程本地的意思,能够想到在ThreadLocal内的都是独属于线程自己。实际也是如此,ThreadLocal对象能够提供线程局部变量,ThreadLocal为变量在每一个线程中都建立了一个副本,每一个线程能够访问本身内部的副本变量。这也意味着多个线程之间互不干扰。算法

怎么用?

通常而言,看一个对象先从构造方法开始,可是ThreadLocal的构造方法为空实现。
image.png数组

那咱们稍微思考一下,既然是储存变量,那么重点就该是查询、增长、删除的方法,分别对应着:get(),set(),remove()方法。spa

get()方法

image.png

  • 首先,获取当前线程,根据当前线程获取Map(ThreadLocal重点)
  • 若是不为空,则继续查询,是否有对应的实体,若是存在则放回。
  • 若是map为空,或者entry为空时,则调用setInitialValue()方法。

使用逻辑仍是很清晰的,接着看下setInitialValue()方法
image.png线程

initialValue()方法是子类重写的方法(),当没有entity的时候,就在这里初始化赋值。对象

当map为空时,则将初始化Map,并将其设置为第一个Entry。若是是Entry为空,则设置Entry。blog

如下是建立map的方法:
image.png内存

set()方法

image.png

简单明了的逻辑,map不为空,则直接设置。若是为空,则建立一个Map。开发

remove() 方法

image.png

看了三个方法 都与ThreadLocalMap有着深厚的联系,那么接下来就看看这个类吧。rem

ThreadLocalMap

为何不用HashMap,而是新建一个类呢?
  • 1、定制key的类型,为弱引用的,以遍处理内存泄漏
  • 2、在 写数据 和 查数据的时候 ThreadLocalMap会有清理过时数据的功能。
  • 3、为了清理过时数据,解决hash冲突的方法,从拉链法,改为了线性开发定址法。
  • 4、为了适应hash冲突解决方法的改变,使数据分布更加均匀,ThreadLocalMap重写了hash算法。使用魔数叠加的hash,能够保证hash的分布均匀。
基础信息
  • 初始容量:16
  • 扩容阈值:2/3
  • hash算法:魔数叠加
  • Entry类型:弱应用 key,正常引用value
resize方法

当扩容达到阈值以后,会触发rehash方法,先清除一轮过时数据,若是清理数据后,数据容量为阈值的3/4,则开启resize方法。get

image.png

resize方法,新建一个数组,将旧数组的从新rehash以后,一一放入后,最后更新引用。并从新计算阈值
image.png

get方法
  • 先根据hash算法找到合适位置,若是这个位置不是,说明发生hash冲突或者不存在,因此须要向后寻找。

image.png

  • 如今就分为两种状况

    • 碰到正常数据,则搜索下一个
    • 碰到null,则开始探测式清理过时逻辑。(这个算是这个类的重要的一个功能)简要的介绍一下流程

      • 开始向后迭代。遇到正常数据时,判断是否处于正确位置,若是是,则不处理,若是不是,则rehash,从新定位(由于以前可能清理出一部分空slot),因此从新rehash后的index理论上会更接近应该处在的index(或者直接处于正确位置)。遇到key=null时,会将当前位置置为空。一直迭代到slot为空时,结束。

image.png

set方法(理解不够透彻)
  • 正常状况,无冲突且为null,就直接添加。
  • 不为null,也分为两种状况,先碰到可key一致的数据,那么替换返回直接·而后就是鹏达过时数据了,就向后进行查找,若是碰到一个key一致的slot,先更新,而后在于当前的这个slot进行替换,若是一直都没有碰到相同的key,那么直接在当前的这个slot生成这个数据。
  • 而后判断是否要扩容。
相关文章
相关标签/搜索