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

ThreadLocal详解

一句话定义

ThreadLocal通过每个线程独有的ThreadLocalMap来存储数据,以ThreadLocal自身为Key,实现线程隔离。

理解过程

ThreadLocal是用于存取当前线程中临时变量的一个工具,Thread中存在ThreadLocalMap的变量,当ThreadLocal设置变量时,先查出当前线程下的ThreadLocalMap,如果为null,则创建ThreadLocalMap,key是当前的ThreadLocal对象,value是要存入的值,再将构建好的ThreadLocalMap赋值给当前线程下的ThreadLocalMap。
image

解决什么问题

ThreadLocal为每个线程提供了独立的变量副本来实现线程安全。
隔离性:每个线程都有自己的ThreadLocalMap,map的value只对当前线程可见,其他线程无法访问。
独立性:即使多个线程操作同一个ThreadLocal实例,但是每个线程都有自己的ThreadLocalMap,只不过key是同一个,最终操作的还是自己的副本。
场景:在web应用中,ThreadLocal常用语存储当前线程的用户信息,确保每个请求处理自己的数据。

最重要的API/动作

get方法

public T get() {  // 获取当前的线程Thread t = Thread.currentThread();  // 通过当前的线程获取ThreadLocalMapThreadLocalMap 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方法

public void set(T value) { Thread t = Thread.currentThread();  ThreadLocalMap map = getMap(t);  // 如果不为空插入k vif (map != null) {  map.set(this, value);  } else {  // 如果是空创建ThreadLocalMap,并插入k vcreateMap(t, value);  }  
}

看下getMap方法和createMap方法,帮助理解上述的代码

ThreadLocalMap getMap(Thread t) {  return t.threadLocals;  
}
void createMap(Thread t, T firstValue) {  t.threadLocals = new ThreadLocalMap(this, firstValue);  
}

remove()

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

当ThreadLocal使用完后被回收后,但是由于ThreadLocalMap是被线程持有,所以不会被回收,但是ThreadLocalMap中仍然存在null->value的引用,如果有长时间占用可能会发生内存泄漏。所以当使用完后手动remove确保资源释放。
remove方法会调用ThreadLocalMap的remove方法中的expungeStaleEntries方法,它会遍历删除key为null的entry。

http://www.hskmm.com/?act=detail&tid=20031

相关文章:

  • C语言 - *进制转*进制 2
  • Functions
  • QOJ #5421. Factories Once More 题解
  • 自动生成验证码
  • 9.23 总结
  • 新品团购 V3 小程序:助力商家高效拓客与直播带货的全能解决方案
  • 事倍功半是蠢蛋56 写业务不要有预设心态
  • 365 赚钱宝小程序系统:多元化变现与趣味运营一体的小程序解决方案
  • 9.22 总结
  • Ansible实现自动化运维 - 实践
  • 每天30道四则运算题目(随机数习题)
  • capsWriter-offline可否支持更小声音输入调研-opus4.1答复
  • git 版本控制
  • 读书笔记:字符与二进制字符串类型详解
  • 析构——循环引用
  • 一些树上问题
  • 如何用 ShedLock 让 Spring Boot 的定时任务在多实例环境下只执行一次
  • 故障处理:Oracle表空间异常增长后又恢复正常的故障模拟与分析
  • Oracle故障分析:lsnrctl start启动监听很慢(AIX平台)
  • 第十届新能源系统、电气与电力国际学术会议 (NESEP 2025)
  • 数据结构 - 二叉树的非递归方式遍历
  • 1208. 翻硬币
  • C# Avalonia 15- Animation- CachingTest
  • CF838D Airplane Arrangements
  • java操作数据库中的bug
  • 事务和Spring常用注解的总结
  • 浅谈SQL应用考试,临时抱佛脚篇
  • 网络安全风险评估指南:CISO如何通过风险评估提升安全防护
  • 藏好自己,做好清理——悼念沈劫匪先生有感
  • macbook m1 安装telnet