深入理解ThreadLocal及其弱引用

简介: 深入理解ThreadLocal及其弱引用

早期版本中:

  • ThreadLocalMap是ThreadLocal的静态内部类,ThreadLocalMap的所有者是ThreadLocal。
  • ThreadLocalMap表中Entry的key为Thread实例。

所以就类似于ThreadLocal维护了所有线程的本地变量。但是这样会导致,
ThreadLocalMap中有大量Entry。
因为ThreadLocal是强引用,所以如果删除线程,对应的ThreadLocalMap不会被删除。导致内存挤压。

因此在JDK1.8之后:

  • ThreadLocalMap的所有者改为Thread。每一个Thread实例拥有一个ThreadLocalMap对象。

因为每一个Thread实例拥有一个ThreadLocalMap对象,所以如果删除线程,对应的ThreadLocalMap会随之销毁。同时也减少了ThreadLocalMap中Entry的数量。

至此早期版本存在的问题得到解决。下面是弱引用的问题。

  • ThreadLocalMap表中Entry的key为ThreadLocal实例,由ThreadLocal向map获取和设置线程变量值。(见下图,来源:极客时间)

image.png

image.png

因为ThreadLocal是Java对象,存放在堆中。所以Thread和ThreadLocalMap访问ThreadLocal是强引用。如果Thread不访问ThreadLocal对象,则强引用消失。
value是存储的局部变量,根据存储需求变化,由用户而不由程序员控制。所以在下一次垃圾回收时 key 会被清理掉,而 value 不会被清理,value 的回收取决于 Thread 对象的生命周期。

如果是ThreadLocalMap的Entry是强引用:
那么,在Thread不访问ThreadLocal对象之后,在下一次垃圾回收时,对应的ThreadLocal对象依然存在。
如果是ThreadLocalMap的Entry是弱引用:
那么,在Thread不访问ThreadLocal对象之后,在下一次垃圾回收时,对应的ThreadLocal对象会被自动清理。

但是,value不会随着ThreadLocal对象清理而被销毁。所以需要及时的remove()操作来减少空间浪费。

img_v3_02h2_b29024f4-a6eb-40cd-8a35-a79c564e723g.jpg

不过,这就意味着使用完 ThreadLocal , CurrentThread 依然运行的前提下。就算忘记调用 remove 方法,弱引用比强引用可以多一层保障:弱引用的 ThreadLocal 会被回收.对应value在下一次 ThreadLocaIMap 调用 set/get/remove 中的任一方法的时候会被清除,从而避免内存泄漏。

参考资料:
https://blog.csdn.net/bbscz007/article/details/105686382
黑马程序员讲ThreadLocal(2020年)
极客时间JUC入门与进阶专栏

相关文章
|
7月前
|
Java
ThreadLocal 场景题
ThreadLocal 场景题
48 1
|
8月前
|
存储 Java 数据管理
ThreadLocal的使用
`ThreadLocal`是Java中的线程局部变量工具,确保每个线程都有自己的变量副本,互不干扰。适用于保持线程安全性数据和跨方法共享数据。基本用法包括创建实例、设置和获取值以及清除值。例如,创建ThreadLocal对象后,使用`.set()`设置值,`.get()`获取值,`.remove()`清除值。注意ThreadLocal可能引起内存泄漏,应适时清理,并谨慎使用以避免影响代码可读性和线程安全性。它是多线程编程中实现线程局部数据管理的有效手段。
99 10
|
存储 SQL Java
ThreadLocal的其他应用
request对象跟PageHelper
109 0
|
存储 Java 数据库连接
对ThreadLocal的一点了解
ThreadLocal是线程变量,它为每个线程提供单独的存储空间。其主要作用是做线程间的数据隔离,也可以用于在同一个线程间方便地进行数据共享。(对于多线程资源共享,加锁机制采用“时间换空间”,ThreadLocal采用“空间换时间”)
137 0
|
存储 Java
对threadlocal了解多少?
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢? JDK 中提供的 ThreadLocal 类正是为了解决这样的问题。 ThreadLocal 类主要解决的就是让每个线程绑定自己的值,可以将 ThreadLocal 类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
|
存储 Java
ThreadLocal理解
ThreadLocal理解
300 0
ThreadLocal理解
|
Java 索引
ThreadLocal尾篇:ThreadLocal内存泄漏到底因为啥
ThreadLocal尾篇:ThreadLocal内存泄漏到底因为啥
ThreadLocal尾篇:ThreadLocal内存泄漏到底因为啥
|
存储 安全 Java
我把 ThreadLocal 能问的,都写了(上)
我把 ThreadLocal 能问的,都写了(上)
我把 ThreadLocal 能问的,都写了(上)
|
存储 缓存 算法
再聊聊ThreadLocal
只要线程处于活动状态并且 ThreadLocal 实例可访问,那么每个线程都持有对其线程局部变量(thread-local)副本的隐式引用。在线程消失后,它的所有线程局部变量(thread-local)副本都将被垃圾回收(除非存在对这些副本的其他引用)
再聊聊ThreadLocal