IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 『Java面经』ThreadLocal 实现原理是什么 & 有哪些引用类型及使用场景? -> 正文阅读

[Java知识库]『Java面经』ThreadLocal 实现原理是什么 & 有哪些引用类型及使用场景?

1、作用

  • ThreadLocal 在多线程环境中,安全的保存线程本地变量,同一线程在某地保存数据,任意地方均可获取。
  • 同一个ThreadLocal ,由于每个线程都有自己的 ThreadLocalMap ,所以不同线程中保存的数据互不影响

2、保存步骤

在这里插入图片描述

  1. 每个线程中都有一个 ThreadLocalMap 变量 threadLocal 来保存 ThreadLocal 中的数据。
  2. threadLocals.set()中,先通过Thread.currentThread()获取当前线程。
  3. 通过getMap(Thread t)获取当前线程的ThreadLocalMap对象。
  4. 当前的 threadLocal作为 key,保存的数据作为 value,构造一个 Entry 对象保存在ThreadLocalMap 中。
  5. 调用 threadLocal.get() 取数据也是先获取到当前线程,以 threadLocal 为 key 从这个 ThreadLocalMap 中取出数据。

3、原理 / 内存泄漏

3.1 数据结构

  1. ThreadLocal 保存一个 value 时,会构造一个 Entry 插入到 ThreadLocalMap 中。
  2. Entry 继承 弱引用类key 指向 ThreadLocal 的弱引用,value 是强引用。

3.2 设计原理

对于一个 ThreadLocal 对象,通常会有两个引用指向它:

  • ①线程中声明的 threadLocal 变量,强引用
  • ②线程底层 ThreadLocalMap 中键值对的 key,弱引用
  • 不需要使用 ThreadLocal 对象时,将变量 threadLocal 置空,让GC回收 ThreadLocal 对象
  • 但是 key 也引用了 ThreadLocal 对象,这个 key 如果是强引用,ThreadLocal 对象就永远不会被回收,但这里设计为弱引用,所以GC 发现 ThreadLocal 对象就会回收它。
  • 但是 ThreadLocalMap 中的 value 是强引用,value 中的对象不会回收,造成内存泄漏。
  • 最佳方法:使用完 ThreadLocal 对象后,主动调用remove()方法,清理对象。

3.3 value如何清理

key 是弱引用,当不存在外部强引用时,会被自动回收。而 value 是强引用,引用链如下

Thread -> ThreadLocal -> Entry -> value

所以只有当 Thread 被回收,value 才会被回收,否则 value 将一直存在,但是让每个线程关闭,是不现实的。在线程池中,大部分线程会伴随着系统的整个周期,那么 value 可能会造成泄漏。

解决方法,在 ThreadLocalMap 进行set(),get(),remove()的时候,都进行清理:

private Entry getEntry(ThreadLocal<?> key) {
    int i = key.threadLocalHashCode & (table.length - 1);
    Entry e = table[i];
    if (e != null && e.get() == key)
        //如果找到key,直接返回
        return e;
    else
        //如果找不到,就会尝试清理(说明key不在了,也就是threadLocal = null)
        //换句话说,这个数据用不上了
        return getEntryAfterMiss(key, i, e);
}

private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
    Entry[] tab = table;
    int len = tab.length;

    while (e != null) {
        // 整个e是entry ,也就是一个弱引用
        ThreadLocal<?> k = e.get();
        //如果找到了,就返回
        if (k == key)
            return e;
        if (k == null)
            //如果key为null,说明弱引用已经被回收了
            //那么就要在这里回收里面的value了
            expungeStaleEntry(i);
        else
            //如果key不是要找的那个,那说明有hash冲突,这里是处理冲突,找下一个entry
            i = nextIndex(i, len);
        e = tab[i];
    }
    return null;
}

真正回收 value 的是 expungeStaleEntry()方法,在 remove 和 set 方法中都会调用这个方法。

ThreadLocal 为了避免内存泄露,不仅使用了弱引用维护 key ,还在每个操作上检查 key 是否被回收,进而再回收value。

3.4 总结

  • ThreadLocal 可能发生内存泄漏。
  • 如果一直没机会调用,set get remove 方法,内存泄漏依旧会发生。
  • 所以养成良好的习惯,用完 ThreadLocal 变量 就主动 remove 它。

4、四种引用类型

1、强引用

  • Object obj = new Object(),除非显示将 obj 置空,否则GC不会回收。
  • 应用场景:对象一般状态。

2、软引用

  • 内存充足,不回收;只有内存不足,再回收。
    SoftReference<String> softReference = new SoftReference<String>(str);
    
  • 应用场景:对象缓存。

3、弱引用

  • 比软引用更弱,被GC扫描到直接回收。
  • 应用场景:对象缓存。

4、虚引用

  • 虚引用不会决定对象的生命周期。如果一个对象只有虚引用,那么和没引用一样,随时被回收。
  • 应用场景:用来跟踪对象被GC回收的活动

5、微信关注『方糖算法』

各类面试资料、内推资源,关注微信公众号获取哦。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-18 17:15:46  更:2021-10-18 17:17:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:24:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码