ThreadLocal
问题描述,在工作中一次请求 请求接口一 ,将request保存到了ThreadLocal,调用接口二,而接口二也存入了ThreadLocal,接口二完成之后将ThreadLocal
romove 了,在此回到接口一时数据已经没有了,导致了问题.
然后就把接口二的 ThreadLocal.remove() 这行代码干掉了......
ThreadLocal 是依存于 ThreadLocalMap 的 ,key 为 Thread.currentThread();
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
在这里先说下对象的强弱软虚 容易记错的就是软和弱什么时候回收问题.
1)软引用(Soft Reference):描述的是一些还有用但非必需的对象.在系统将会发生内存溢出之前,会把这些对象列入回收范围进行二次回收,也就是说系统将会发生内存溢出了,才会对他们进行回收.
2)弱引用(Weak Reference):程度比软引用更弱一些.这些对象只能生存到下次 GC 之前.当 GC 工作时扫描到,无论内存是否足够都会将其回收.
从这里我们可以发现 k 为弱引用.v为强引用.
如果key被回收掉,则v可能发生内存泄露.
static ThreadLocal threadLocal = new ThreadLocal();
这种用法一个线程 一个线程永远只有一个KV对,并且不会被回收掉,只能是覆盖,跟随JVM启动而启动,结束而结束,可以remove删除掉自己设置的kv.
另外一种用法
class Test{
ThreadLocal threadLocal = new ThreadLocal();
}
用对象持有 Test test = new Test(); test.threadLocal.set();
如果对象使用完毕被回收(test=null; System.gc;),没有调用 threadLocal.remove();
那这个 threadLocal 没有被回收,随着GC发生K被回收掉,这时候V就永远不会被回收,即使当前线程在此赋值,就会产生一条新纪录,导致内存堆积越来越多,OOM.
JDK解决方案,当前线程 一定要在调用 get set remove 方法 会清理当前线程ThreadLocal空间内K为空的数据,赋值为NULL,帮助清理.
自己解决就是一定要按规定调用remove.
----------------------------------------------------------------
本文来自博客园,作者:苏子墨,转载请注明原文链接:https://www.cnblogs.com/li-xiaotian/p/16602114.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix