当前位置: 首页 > news >正文

【Java】浅谈ThreadLocal

一,概述

ThreadLocal,其作用是实现线程独享数据,用于隔离每个线程对于同一个值的访问,核心方法只有三个:

ThreadLocal#set 设置线程独享数据

ThreadLocal#get 获得线程独享数据

ThreadLocal#remove清除线程独享数据

本文主要谈谈ThreadLocal基本使用、实现原理、以及使用注意事项的讨论。

二,实例

public class ThreadLocalMain {//定义一个ThreadLocalpublic static final ThreadLocal<Integer> threadLocal = new ThreadLocal<>() {@Overrideprotected Integer initialValue() {//重写initialValue方法,否则默认返回null作为初始值System.out.println("init value for thread:" + Thread.currentThread().getName());return Thread.currentThread().hashCode();}};public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {//线程中getSystem.out.println(threadLocal.get());//线程中setthreadLocal.set(1);//线程中removethreadLocal.remove();}).start();}}
}

三,原理

ThreadLocal既然线程数据独享,则必定有一个线程->数据映射的map,这个map要么放置在Thread、要么放置在ThreadLocal。显然放在Thread合理,因为ThreadLocal实例存在多个,ThreadLocal自身可以作为一个key,绑定到每个Thread的map中,所需创建的map较少,且不改变Thread的引用。如果将map放置到ThreadLocal,显然ThreadLocal会引用到Thread,不利于Thread的gc。

关于在于怎么设计,ThreadLocal本身即为一个key。

在java实现中,这个map放置在Thread

Thread.map = ThreadLocal.ThreadLocalMap threadLocals;

这是一个数组实现的map,具体实现此处不赘述。

1,get

get只暴露如下方法

以上逻辑分三步走,

1,拿到线程map

2,将ThreadLocal实例作为key,从map中取值并返回

3,如果未set值,则调用setInitialValue方法初始化

getMap方法实现如下,很简单,直接取thread#threadLocals

对于map为null或未设置值的情况,会走setInitialValue,跟进看下逻辑

如果map存在直接set即可,否则通过creatMap创建map,

创建方式很简单,传入初始key和value即可,

这样,Thread上下文中就可通过Thread#threadLocal获得ThreadLocal作为key的value了。

2,set

set方法与setInitialValue方法逻辑类似,就不赘述了

核心在于set中有一个关于引用的特殊处理,能规避一些内存泄漏,咱们看下

2 是对ThreadLocal是否gc的判断,如果已经gc,refersTo返回false。

3 如果ThreadLocal已经gc,则重新新建一个引用关系,赋值。

Entry声明如下

可以看到,ThreadLocal作为key是以弱引用方式,传入到Entry中,即Map对应散列表Node。

但set的值,仍是强引用保存到Thread#threadLocals#Entry[]中。以上只对ThreadLocal本身做了内存泄漏防护,对保存的value如果不及时remove,是会一直存在于Thread中,直至Thread销毁

3,remove

remove比较简单,不赘述

http://www.dtcms.com/a/337657.html

相关文章:

  • 【WSL2笔记10】WSL-Ubuntu 环境下 ComfyUI 本地部署性能最大化指南
  • 生产环境慎用 context.Background ():你的系统可能在 “空转”
  • CVPR 2025|英伟达联合牛津大学提出面向3D医学成像的统一分割基础模型
  • 【统刷】专题完结,题单汇总
  • 抽象工厂设计模式 Abstract Factory
  • Layui COP证书管理系统
  • html页面打水印效果
  • 码上爬第十八题【协程+webpack】
  • mongodb的高可用部署
  • ParallelWaveGAN-KaldiFree:纯Pytorch的PWG
  • 【datawhale组队学习】RAG技术 - TASK01
  • SQLsever基本操作
  • 可实时交互的AI生成世界,腾讯发布的AI框架Yan
  • keil报错:ERROR :FILE DOES NOT EXIST
  • SAP ERP移动类型 MovementType (|MM|SD|PP|FICO)
  • STL库——string(类函数学习)
  • Lucene 8.5.0 的 `.pos` 文件**逻辑结构**
  • Mybatis执行sql流程(二)之加载Mapper
  • SQL详细语法教程(六)存储+索引
  • 高效长尾关键词SEO优化
  • 汽车企业顾客满意度调查:全周期反馈解码方案(市场调研实践)
  • Redis 哨兵模式与主从架构对比
  • 江苏单电感M401A-晶晨S905L3A_频率1.5ghz赫兹_2+16G_安卓9_线刷固件包
  • iOS 应用上架全流程实践,从开发内测到正式发布的多工具组合方案
  • 决策树-信息增益(第二十三节课内容总结)
  • 上网行为安全管理与组网方案
  • 第四十天(Vue)
  • 【VUE】解决Vue路由重复导航报错
  • 嵌入式软件开发笔试题练习
  • 微算法科技(NASDAQ: MLGO)研究分片技术:重塑区块链可扩展性新范式