ThreadLocal原理

ThreadLocal简介

ThreadLocal,即线程变量,指ThreadLocal中的变量属于当前线程,并且该变量是线程隔离的。
每个线程都会在 ThreadLocal 中保存一份该线程独有的数据,所以它是线程安全的。

ThreadLocal原理

底层数据结构

ThreadLocal 底层是通过 ThreadLocalMap 这个静态内部类来存储数据的,ThreadLocalMap 就是一个键值对的 Map,它的底层是 Entry 对象数组,Entry 对象中存放的键是 ThreadLocal 对象,值是 Object 类型的具体存储内容。
在这里插入图片描述

哈希冲突

ThreadLocal 的散列方式,称为 斐波那契散列 。
虽然这种方式能够充分散列,但还是无法避免出现哈希冲突。

  • 如果散列值已存在且 key 为同一个对象,直接更新 value
  • 如果散列值已存在但 key 不是同一个对象,尝试在下一个空的位置进行存储

处理哈希冲突的方法:
如果在 set 时遇到哈希冲突,ThreadLocal 会尝试在数组下一个索引位置进行存储,同时在 set 过程中 ThreadLocal 会释放 key 为 NULL,value 不为 NULL 的脏 Entry对象的 value 属性来防止内存泄漏 。

扩容机制

ThreadLocalMap 的初始容量是 16。

// 初始化容量
private static final int INITIAL_CAPACITY = 16;

扩容机制:

  • ThreadLocalMap的set(ThreadLocal<?> key, Object value) 方法中可能会触发启发式清理,在清理无效 Entry 对象后,如果数组长度大于等于数组定义长度的 2/3,则首先进行 rehash;
  • rehash 会触发一次全量清理,如果数组长度大于等于数组定义长度的 1/2,则进行 resize(扩容);
  • 进行扩容时,Entry 数组为扩容为 原来的2倍 ,重新计算 key 的散列值,如果遇到 key 为 NULL 的情况,会将其 value 也置为 NULL,帮助虚拟机进行GC。

内存泄露

Entry 对象的 key 即 ThreadLocal 类是继承于 WeakReference 弱引用类。在发生 GC 活动时,无论内存空间是否足够,垃圾回收器都会回收具有弱引用的对象。
在发生 GC 活动时,若 ThreadLocal 类没有外部强引用,就会将 ThreadLocal 对象回收。

解决:
主动解决:
使用完 ThreadLocal 中存储的内容后将它 remove 掉就可以了。

ThreadLocal内部防止内存泄露:
ThreadLocalMap的rehash() 方法中会对 ThreadLocalMap 进行一次全量清理,全量清理会遍历整个 Entry 数组,删除所有 key 为 NULL,value 不为 NULL 的脏 Entry对象。

使用场景

  • 1、每个线程需要有自己单独的实例
  • 2、实例需要在多个方法中共享,但不希望被多线程共享

使用场景:
1)存储用户Session
2)数据库连接,处理数据库事务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值