type
Post
status
Published
date
Feb 6, 2025
slug
ThreadLocal
summary
ThreadLocal 是 Java 中所提供的线程本地存储机制,可以利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻、任意方法中获取缓存的数据。
tags
线程
category
技术分享
icon
fa-solid fa-file
password

ThreadLocal 底层实现

ThreadLocal 是 Java 中所提供的线程本地存储机制,可以利用该机制将数据 缓存在某个线程内部 ,该线程可以在任意时刻、任意方法中获取缓存的数据。
notion image
ThreadLocal 底层是通过 ThreadLocalMap 来实现的,每个 Thread 对象中都存在一个 ThreadLocalMap 变量,这个 Mapkey 就是我们要操作的 ThreadLocal 对象,Mapvalue 为需要缓存的值。
我们在使用 ThreadLocal 的时候其实就是拿到当前线程中的 ThreadLocalMap 中的 keyvalueThreadLocal 本身不过是个工具类罢了。

注意事项

如果在线程池中使用 ThreadLocal 可能会造成内存泄漏,因为当 ThreadLocal 对象使用完之后,应该要把设置的 keyvalue——也就是 Entry 对象进行回收。但线程池中的线程不会回收,并且 Thread 对象是通过强引用指向 ThreadLocalMapThreadLocalMap 也是通过强引用指向 Entry 对象,线程不被回收,Entry 对象也就不会被回收,从而导致不再使用的 Entry 对象越来越多,出现内存泄漏。
解决办法是,在使用了 ThreadLocal 对象之后,手动调用 ThreadLocalremove() 方法,手动清除 Entry 对象。
notion image
实线箭头是强引用,虚线箭头是弱引用
^4efc86
总结:当你在一个方法/栈中创建 ThreadLocal,该对象就被栈强引用着,直到方法执行完毕,栈被销毁,失去了强引用的、只有 ThreadLocalMap.Entry 弱引用的 ThreadLocal 就会被 GC 回收,但 ThreadLocalMap.Entry 中的 value 却实打实强引用了一个对象,entry 不死它就不死,所以说养成良好习惯 new ThreadLocal()ThreadLocal.remove() 要在方法中成对出现。

应用场景

当一个变量是共享的(成员变量、static 等),但是需要每个线程互不影响,相互隔离,就可以使用 ThreadLocal。
  1. 跨层传递信息的时候,每个方法都声明一个参数很麻烦,A、B、C、D 4 个类互相传递,每个方法都声明参数降低了维护性,可以用一个 ThreadLocal 共享变量,在 A 存值, B、C、D 都可以获取。
  1. 隔离线程,存储一些线程不安全的工具对象,如(SimpleDateFormat)。
  1. Spring 中的事务管理器就是使用的 ThreadLocal,这也是为什么声明式事务如果用到了多线程,它是没有办法达到一致性的,因为一个线程就存储了一个事务。
  1. SpringMVC 的 HttpSession、HttpServletReuqest、HttpServletResponse 都是放在 ThreadLocal,因为 servlet 是单例的,而 SpringMVC 允许在 controller 类中通过@Autowired 配置 request、response 以及 requestcontexts 等实例对象,在任何地方获取请求都永远是当前的请求。底层就是搭配 ThreadLocal 才实现线程安全。
浅谈一下HashMapJWT
Loading...
林明菁
林明菁
一个思念的人
公告

🎉欢迎你来到我的博客🎉

去右下角歌单里点首歌听吧
因为博客里没什么好看的

🔰版本号:NotionNext 4.8.3🔰