关于java:面试官ThreadLocal-为什么会内存泄漏吗是怎么产生的面试必问

41次阅读

共计 1703 个字符,预计需要花费 5 分钟才能阅读完成。

原文:blog.csdn.net/qunqunstyle99/article/details/94717256

ThreadLocal 是什么

ThreadLocal 是一个本地线程正本变量工具类。次要用于将公有线程和该线程寄存的正本对象做一个映射,各个线程之间的变量互不烦扰,在高并发场景下,能够实现无状态的调用,特地实用于各个线程依赖不通的变量值实现操作的场景。

下图为 ThreadLocal 的外部结构图

从下面的结构图,咱们曾经窥见 ThreadLocal 的外围机制:

  • 每个 Thread 线程外部都有一个 Map。
  • Map 外面存储线程本地对象(key)和线程的变量正本(value)
  • 然而,Thread 外部的 Map 是由 ThreadLocal 保护的,由 ThreadLocal 负责向 map 获取和设置线程的变量值。

所以对于不同的线程,每次获取正本值时,别的线程并不能获取到以后线程的正本值,造成了正本的隔离,互不烦扰。

举荐一个开源收费的 Spring Boot 最全教程:

https://github.com/javastacks/spring-boot-best-practice

ThreadLocalMap

ThreadLocalMap 是 ThreadLocal 的外部类,没有实现 Map 接口,用独立的形式实现了 Map 的性能,其外部的 Entry 也独立实现。

和 HashMap 的最大的不同在于,ThreadLocalMap 构造非常简单,没有 next 援用,也就是说 ThreadLocalMap 中解决 Hash 抵触的形式并非链表的形式,而是采纳线性探测的形式。(ThreadLocalMap 如何解决抵触?

在 ThreadLocalMap 中,也是用 Entry 来保留 K - V 构造数据的。然而 Entry 中 key 只能是 ThreadLocal 对象,这点被 Entry 的构造方法曾经限定死了。

static class Entry extends WeakReference<ThreadLocal> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal k, Object v) {super(k);
        value = v;
    }
}

留神了!!

Entry 继承自 WeakReference(弱援用,生命周期只能存活到下次 GC 前),但只有 Key 是弱援用类型的,Value 并非弱援用。(问题马上就来了)

因为 ThreadLocalMap 的 key 是弱援用,而 Value 是强援用。这就导致了一个问题,ThreadLocal 在没有内部对象强援用时,产生 GC 时弱援用 Key 会被回收,而 Value 不会回收。

当线程没有完结,然而 ThreadLocal 曾经被回收,则可能导致线程中存在 ThreadLocalMap<null, Object> 的键值对,造成内存泄露。(ThreadLocal 被回收,ThreadLocal 关联的线程共享变量还存在)。

如何防止透露

为了避免此类情况的呈现,咱们有两种伎俩。

1、应用完线程共享变量后,显示调用 ThreadLocalMap.remove 办法革除线程共享变量;

既然 Key 是弱援用,那么咱们要做的事,就是在调用 ThreadLocal 的 get()set() 办法时实现后再调用 remove 办法,将 Entry 节点和 Map 的援用关系移除,这样整个 Entry 对象在 GC Roots 剖析后就变成不可达了,下次 GC 的时候就能够被回收。

2、JDK 倡议 ThreadLocal 定义为private static,这样 ThreadLocal 的弱援用问题则不存在了。

文章参考:

  • www.jianshu.com/p/98b68c97df9b
  • www.cnblogs.com/coshaho/p/5127135.html

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿(2022 最新版)

2. 劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0