ThreadLocal
ThreadLocal
作用:
- 提供线程内局部变量,多线程场景下不同线程之间不会相互干扰。
- ThreadLocal 实例通常来说都是 private static 修饰的,用于关联线程、线程上下文。
- 减少同一个线程内的函数 或 组件之间传递变量的复杂性。
基本方法:
demo:
ThreadLocal处理多线程问题,将变量与线程绑定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class ThreadLocalDemo { private String Msg; ThreadLocal<String> threadLocal = new ThreadLocal<>(); private String getMsg(){ return threadLocal.get(); } private void setMsg(String s){ threadLocal.set(s); } public static void main(String[] args) { ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo(); for ( int i = 0 ;i< 10 ;i++){ Thread thread = new Thread( new Runnable() { @Override public void run() { threadLocalDemo.setMsg(Thread.currentThread().getName()+ "的数据" ); System.out.println( "--------------------------------------" ); System.out.println(Thread.currentThread().getName()+ ", 保存的数据------>" + threadLocalDemo.getMsg()); } }); thread.start(); } } } |
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Thread-0, 保存的数据------>Thread-0的数据 -------------------------------------- Thread-1, 保存的数据------>Thread-1的数据 -------------------------------------- Thread-2, 保存的数据------>Thread-2的数据 -------------------------------------- Thread-3, 保存的数据------>Thread-3的数据 -------------------------------------- Thread-4, 保存的数据------>Thread-4的数据 -------------------------------------- Thread-5, 保存的数据------>Thread-5的数据 -------------------------------------- Thread-6, 保存的数据------>Thread-6的数据 -------------------------------------- Thread-7, 保存的数据------>Thread-7的数据 -------------------------------------- Thread-9, 保存的数据------>Thread-9的数据 -------------------------------------- Thread-8, 保存的数据------>Thread-8的数据 |
验证可知,每个线程拿到的都是自己的数据。
ThreadLocal数据结构:
ThreadLocal的设计是:每个Thread维护一个ThreadLocalMap哈希表,这个哈希表的key是ThreadLocal实例本身,value才是真正要存储的值Object。
(1) 每个Thread线程内部都有一个Map (ThreadLocalMap)
(2) Map里面存储ThreadLocal对象(key)和线程的变量副本(value)
(3) Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。
(4) 对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰。
ThreadLocal可能引起的问题:
内存泄漏
问题背景:
- 源码可知,在ThreadLocalMap中,用Entry来保存K-V结构数据的。但是Entry中key是ThreadLocal对象。
- 源码可知,Entry继承WeakReference,使用弱引用,可以将ThreadLocal对象的生命周期和线程生命周期解绑。
- 强引用( “Strong” Reference) , 最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾回收器就不会回收这种对象。
- 弱引用( WeakReference) ,垃圾回收器发现只具有弱引用的对象,无论当前内存空间足够与否,都会回收。
问题原因:在当前线程依旧运行情况下,业务代码中使用完线程的ThreadLocal对象后被回收,则TheadLocalMap中Entry的key为null,此时Entry中value依然存在,且key为null,则value无法被访问到,内存泄漏。
处理方式:使用完ThreadLocal ,手动调用其remove方法删除对应的Entry。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)