当前位置: 首页 > news >正文

面试分析:你懂不懂threadlocal?

目录

ThreadLocal

应用场景

get与set方法

ThreadLocalMap

ThreadLocalMap.set

 ThreadLocalMap.get

 ThreadLocalMap.remove

线程隔离

内存泄漏


今天看一个面试题,threadlocal的原理

首先,要知道threadlocal是什么,如果都不知道这个是什么,那就也别看什么原理了.....

ThreadLocal

threadlocal 是线程的内部存储类,可以在指定线程内存储数据,且只有指定线程可以拿到数据

说白了,就是为了数据安全

不同的线程在使用 threadlocal 的时候,都会有自己的一个 threadlocalmap 对象,并且通过 threadlocal 进行管理

每个新线程都会被实例化一个 threadlocalmap,并且赋值给 threadLocals,如果已经存在了 threadLocals,那就直接复用

应用场景

那种作用域是线程,并且不同的线程还会有不同的副本的时候,就可以考虑用 threadlocal

当然,如果说业务处理逻辑强依赖与 副本变量,那可能就不大适合这玩意了

get与set方法

这一块我们可以直接看源码就行

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

可以看到,无论是 get 还是 set,都是用的 ThreadLocalMap 的方法

ThreadLocalMap

ThreadLocalMap 为每个 thread 都维护了一个数组 table,threadllcal 确定了一个数组下标,而这个下标是value存储的对应位置

从之前的 set 源码,我们可以得到,ThreadLocalMap 是一个延迟创建的结构,也就是说,至少要放置一个内容时才会创建

而通过创建 ThreadLocalMap 的源码,我们可以得到,ThreadLocalMap 初始化时创建了默认长度是16的 Entry 数组。通过 hashCode 与 length 位运算确定索引值 i

ThreadLocalMap.set

我们来看看 threadLocalMap 的 set 方法

 ThreadLocalMap.get

get 方法没有什么可看的,就直接取就完事了

 ThreadLocalMap.remove

我们再看看 remove 方法

        private void remove(ThreadLocal<?> key) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }

可以看到,也没什么东西

线程隔离

threadlocal 拥有线程隔离特性,只有线程内可以访问

类比 synchronized,它是通过线程等待来解决访问冲突问题

而 threadlocal 是通过空间存储来解决访问冲突问题

内存泄漏

注意,threadlocal 有一个地方需要注意,那就是内存泄漏的问题,使用完,一定要 remove,否则永远清除不掉,时间长了就会出问题了

相关文章:

  • ESP8266-Arduino编程实例-CCS811数字气体传感器驱动
  • 【C++编程语言】之类和对象---对象初始化和清除
  • Task05|joyfulpandas|变形
  • 【SpringBoot】yaml配置文件语法—总结回顾
  • jenkins 发布项目到k8s tomcat
  • 基于ssm(非maven)学生考勤管理系统
  • C++11新特性(一)
  • WebRTC源码之摄像头视频数据采集源码分析
  • stm32f4xx-PWM输出
  • 【博客474】为什么k8s控制面pod使用的ip是node ip,而非pod cidr中的ip
  • 2022 华为 Java 高级面试题及答案
  • SpringCloud集成RocketMQ
  • 计算机java毕业设计选题汇总(2022)
  • Ruby on Rails 实践:课程导读
  • OpenGL基本架构知识
  • python3.6+scrapy+mysql 爬虫实战
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • express.js的介绍及使用
  • LeetCode算法系列_0891_子序列宽度之和
  • MySQL数据库运维之数据恢复
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SQL 难点解决:记录的引用
  • Sublime Text 2/3 绑定Eclipse快捷键
  • underscore源码剖析之整体架构
  • Vue2 SSR 的优化之旅
  • vue数据传递--我有特殊的实现技巧
  • 创建一个Struts2项目maven 方式
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • - 概述 - 《设计模式(极简c++版)》
  • 关于Java中分层中遇到的一些问题
  • 前嗅ForeSpider教程:创建模板
  • 使用 @font-face
  • 使用权重正则化较少模型过拟合
  • 算法-插入排序
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 最近的计划
  • HanLP分词命名实体提取详解
  • Java总结 - String - 这篇请使劲喷我
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • #考研#计算机文化知识1(局域网及网络互联)
  • $NOIp2018$劝退记
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (八十八)VFL语言初步 - 实现布局
  • (二)WCF的Binding模型
  • (汇总)os模块以及shutil模块对文件的操作
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (实战篇)如何缓存数据
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)VC++中ondraw在什么时候调用的
  • .net core 6 redis操作类
  • .net Signalr 使用笔记
  • .NET 表达式计算:Expression Evaluator