ThreadLocal了解

news/2024/11/28 17:39:50/

文章目录

    • 概述
    • 源码
    • 原理
    • 内存泄露
    • 应用场景

概述

  • ThreadLocal提供线程的局部变量,这种变量与普通变量的区别在于,每个访问这种变量的线程都有自己的、独立的变量副本。用于解决多线程间的数据隔离问题。

源码

//返回Thread实例的成员变量threadLocals
ThreadLocalMap getMap(Thread t) {return t.threadLocals;
}

ThreadLocals 依赖于附加到每个线程的每线程线性探测哈希映射(Thread.threadLocals 和 inheritableThreadLocals)。ThreadLocal 对象充当键,通过 threadLocalHashCode 进行搜索。这是一个自定义哈希代码(仅在 ThreadLocalMap 中有用),它消除了相同线程使用连续构造的 ThreadLocals 的常见情况下的冲突,同时在不太常见的情况下保持良好的行为。

get方法

返回此线程局部变量的当前线程副本中的值。如果变量没有当前线程的值,则首先将其初始化为调用该方法返回 initialValue 的值。

public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();
}

set方法

将此线程局部变量的当前线程副本设置为指定值。大多数子类不需要重写此方法,仅依靠该方法 initialValue 来设置线程局部变量的值。

public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);
}

remove方法

删除此线程局部变量的当前线程值。如果此线程局部变量随后由当前线程 读取 ,则其值将通过调用其方法重新初始化,除非其 initialValue 值在此期间由当前线程 设置 。这可能会导致在当前线程中多次调用 initialValue 该方法。

public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);
}

原理

在这里插入图片描述

多线程隔离

  • ThreadLocal提供线程局部变量。这些变量与普通对应变量的不同之处在于,访问一个变量的每个线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是希望将状态与线程(例如,用户 ID 或事务 ID)相关联的类中的私有静态字段。
  • 只要线程处于活动状态并且 ThreadLocal 实例可访问,每个线程都包含对其线程局部变量副本的隐式引用;线程消失后,其线程本地实例的所有副本都将受到垃圾回收(除非存在对这些副本的其他引用)。

ThreadLocalMap

  • ThreadLocalMap 是一个自定义的哈希映射,仅适用于维护线程本地值。不会在 ThreadLocal 类外部导出任何操作。该类是包私有的,允许在类 Thread 中声明字段。为了帮助处理非常大且长期存在的用法,哈希表条目对键使用 WeakReferences。但是,由于不使用引用队列,因此仅当表开始空间不足时,才能保证删除过时的条目。

内存泄露

  • ThreadLocalMap中的key是弱引用,而value是强引用。所以,如果ThreadLocal没有被外部强引用的情况下,在垃圾回收时,key会被清空掉,而value不会。ThreadLocal中就会出现key为null的Entry。假如我们不采取措施,value永远不会被GC回收,这个时候就可能会产生内存泄漏问题。
  • 解决办法:使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。

为什么key使用弱引用?

  • 如果使用强引用,当ThreadLocal 对象的引用(强引用)被回收了,ThreadLocalMap本身依然还持有ThreadLocal的强引用,如果没有手动删除这个key ,则ThreadLocal不会被回收,所以只要当前线程不消亡,ThreadLocalMap引用的那些对象就不会被回收, 可以认为这导致Entry内存泄漏。

强引用:普通的引用,强引用指向的对象不会被回收;
软引用:仅有软引用指向的对象,只有发生gc且内存不足,才会被回收;
弱引用:仅有弱引用指向的对象,只要发生gc就会被回收。

应用场景

  • 数据库事务:通过AOP的方式,对执行数据库事务的函数进行拦截。函数开始前,获取connection开启事务并存储在ThreadLocal中,任何用到connection的地方,从ThreadLocal中获取。函数执行完毕,提交事务释放connection。
  • 用户登录信息:用户登录信息好多个方法上都要用到,给每个方法都添加一个User非常麻烦,而且有些时候,如果调用链有无法修改源码的第三方库,User对象就传不进去了。而ThreadLocal可以在一个线程中传递同一个对象。
  • RequestContextHolder:Spring 提供的一个用来暴露 Request 对象的工具,利用 RequestContextHolder,可以在一个请求线程中获取到 Request,避免了 Request 从头传到尾的情况。一般项目中,会对这个类再次进行封装,便于获取请求的相关的信息,常见的比如用户信息。

总结起来使用的场景就是一下这些地方:

在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
线程间数据隔离
进行事务操作,用于存储线程事务信息。
数据库连接,Session会话管理。

你知道的越多,你不知道的越多。


http://www.ppmy.cn/news/382918.html

相关文章

算法分析和大O简介

在本文中,我们将讨论如何分析算法以及为什么这样做很重要! 为什么要分析算法? 在我们开始之前,让我们澄清一下什么是算法。在本文中,算法只是解决问题的过程或公式。有些问题非常有名,以至于算法都有名字…

冰点文库最新版3210

冰点文库最新版v3210 链接: https://pan.baidu.com/s/1zgb5b6Xsh-tSvHve1ORIZg 提取码: tpsj

文库下载软件 冰点文库下载器 软件 百度网盘链接地址

链接:https://pan.baidu.com/s/11idYXB3vQrP5f5hMouLsHg 提取码:qk8w

【冰点文库下载器.exe】

【冰点文库下载器.exe】 免费下载文档内资料的冰点文库下载器,可以下载百度文库文档,自动转化为PDF文档,免费下载网页的付费资料 教程:文档下载具体操作步骤: 第一步:双击打开文库运用.exe 第二步&#xf…

冰点破解版,百度文库免费下载

冰点文库介绍:冰点文库下载器,下载文档利刃当之首选!无需积分也无需登录就可以自由下载百度和豆丁文库,它支持百度、豆丁、丁香、畅享、MBALib、HP009、MAX、Book118、金字塔医学、大桔灯等文库文档,支持多个任务同时下…

分享冰点文库去广告版

这款工具下载下来的文档格式为PDF,PDF文档无法直接修改,使用起来并不如直接下载源文档好用。而且官方版还有有大量的捆绑广告。 但可以自由下载百度,豆丁,道客巴巴,丁香,畅享网等11个网站的文档&#xff0c…

冰点文库下载器绿色版V3.2.15(0914)

介绍: 冰点文库下载器,免费下载文档工具,无需积分也无需登陆就能自由下载百度文库、豆丁网、丁香网、电器网、MBAlib智库、爱问文档、畅享、IT168、HP009、MAX、Book118、道客巴巴、金字塔医学、大桔灯等文库文档,支持多任务同时…

冰点免费文档下载

下面给大家推荐一款极好的可以帮助我们免费下载文档内资料的软件–冰点客户端,可以下载百度文库,豆丁网上的付费资料。 链接:https://pan.baidu.com/s/1Y3GiUTIu_Nq5olZ1i6KJLg 提取码:qbxa 复制这段内容后打开百度网盘手机App&am…