码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 面试题: 谈一谈对 ThreadLocal 的理解


    目录

    • 目的
    • 资源
    • 核心结论
    • 原理
    • 代码演示
    • 其他
      • 为什么 ThreadLocalMap 中的key要设计为弱引用
    • 参考资源
      • 内存泄漏问题
      • ThreadLocals下标计算
      • 源码分析

    目的

    学习记录, 面试准备

    资源

    B站的一个讲高频面试题的一个学习视频

    核心结论

    线程之间资源隔离, 线程内资源共享.

    原理

    每个线程内有一个 ThreadLocalMap 类型的成员变量, 用来存储资源对象
    ① 调用 set(), 就是以 ThreadLocal 自己作为key, 资源对象作为 value, 存入到当前线程的 ThreadLocalMap 中
    ② 调用 get(), 就是以 ThreadLocal 自己作为key, 到当前线程中查找关联的资源值
    ③ 调用 remove(), 就是以 ThreadLocal 自己作为key, 移除当前线程关联的资源值

    代码演示

    /**
     * TestThreadLocal: 线程之间资源隔离, 线程内资源共享
     *
     * @author xiaozhengN 571457082@qq.com
     * @since 2022-11-27 22:12:39
     **/
    @Slf4j
    public class TestThreadLocal {
        public static void main(String[] args) {
            test1();
            test2();
        }
    
        /**
         * 多个线程调用, 得到的是自己的Connection对象
         */
        private static void test1() {
            for (int i = 0; i < 5; i++) {
                new Thread(() -> log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection()), "test1Thread" + (i + 1)).start();
            }
        }
    
        /**
         * 一个线程内调用, 得到的是同一个Connection对象
         */
        private static void test2() {
            for (int i = 0; i < 3; i++) {
                new Thread(() -> {
                    log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection());
                    log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection());
                }, "test2Thread" + (i + 1)).start();
    
            }
        }
    
        static class Utils {
            // 线程隔离
            private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    
            /**
             * 获取连接
             *
             * @return Connection对象
             */
            public static Connection getConnection() {
                Connection connection = threadLocal.get();
                if (connection == null) {
                    connection = innerGetConnection();
                    threadLocal.set(connection);
                }
                return connection;
            }
    
            private static Connection innerGetConnection() {
                try {
                    return DriverManager.getConnection("jdbc:mysql://localhost:3306/bos?useSSL=false", "root", "root");
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    其他

    为什么 ThreadLocalMap 中的key要设计为弱引用

    ① Thread 可能需要长时间运行(如线程池中的线程), 如果 key 不再使用, 需要 GC 去回收.
    ② 但 GC 仅仅是释放 key 可内存, 后续还要根据 key 是否为 null 来进一步释放value的内存, 释放时机如下:
    2.1 获取 key 发现 null key
    2.2 set key时, 会使用启发式扫描, 清除临近的 null key, 启发次数与元素个数, 是否发现null key有关
    2.3 remove时(推荐), 因为一般使用 ThreadLocal 时都把它作为静态变量, 因此 GC 无法回收.

    参考资源

    内存泄漏问题

    ThreadLocal内存泄漏

    ThreadLocals下标计算

    一个特殊的常量 0x61c88647
    0x61c88647

    源码分析

    源码走读

  • 相关阅读:
    mysql启动报错:ERROR! The server quit without updating PID file
    基于JAVA计算机类课程实验平台计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    【Linux入门】— 腾讯云服务器的搭建
    详解卡尔曼滤波原理
    模拟验证码发送
    Arduino驱动BNO055 10轴绝对定向传感器(惯性测量传感器篇)
    使用OpenCV将图像转换为NV12格式并加载NV12数据
    php学习笔记
    常用傅里叶变换表
    react antd -Form表单 (单个对象合并成整体对象) 合并对象
  • 原文地址:https://blog.csdn.net/xiaozhengN/article/details/128078727
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号