ThreadLocal源码解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: ThreadLocal源码解析

@[toc]

前言

  • ThreadLocal 想必大家都非常熟悉了,这个不再多做ThreadLocal 的使用案例,,如果有不熟悉的小伙伴 可以阅读

ThreadLocal的源码

本节 我们详细了解ThreadLocal的源码,让大家更为了解ThreadLocal

ThreadLocalMap

在这里插入图片描述
ThreadLocal中的嵌套内部类ThreadLocalMap,这个类本质上是一个map,和HashMap之类的实现相似,依然是key-value的形式,其中有一个内部类Entry,其中key可以看做是ThreadLocal实例,但是其本质是持有ThreadLocal实例的弱引用

在这里插入图片描述
ThreadlocalMap 会发现他是ThreadLocal 的一个内部类,

会发现他有一个Entry

**Entry继承WeakReference,使用弱引用,可以将ThreadLocal对象的生命周期和线程生命周期解绑,持有对ThreadLocal的弱引用,可以使得ThreadLocal在没有其他强引用的时候被回收掉,这样可以避免因为线程得不到销毁导致ThreadLocal对象无法被回收。并且
他是 以key value 形式的Entry **

有兴趣的同学可以打开 底层源码看下具体实现

initialValue

在这里插入图片描述

initialValue ThreadLocal初始化的方法,默认为 null ,可以重写

在这里插入图片描述

get 方法

会发现他把 Thread.currentThread(); 传到 getMap() 方法中,
在这里插入图片描述
调用Thread 类 中定义的 Threadlocal.ThreadlocalMap() 返回一个map
判断当前线程的map是否存在,不为空, 获取当前Entry 实例,
判断这个键值对是否为空
如果不是空,就返回对应的value值
此处是当前线程的map不存在,返回setInitialValue,为空返回初始化值

这里有个非常重要的知识,initialValue 是使用懒加载 ,只有调用 get 的时候才会 使用initialValue 方法,在 new ThreadLocal 中是不会初始化的


private T setInitialValue() {
    //获取初始化值,默认为null(如果没有子类进行覆盖)
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    //不为空不用再初始化,直接调用set操作设值
    if (map != null)
        map.set(this, value);
    else
        //第一次初始化,createMap在上面介绍set()的时候有介绍过。
        createMap(t, value);
    return value;
}

接下来我们看下 set的方法

set方法

在这里插入图片描述
调用Thread 类 中定义的 Threadlocal.ThreadlocalMap() 返回一个map
判断当前线程的map是否存在,如果ThreadLocal中有这个map,就把当前类和对应的值传进去

如果没有这个map,就新建一个t线程的ThreadLocalMap,并将value值传进去

remove方法

在这里插入图片描述
remove方法就比较简单了

相关文章
|
6天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
19 2
|
6天前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。
|
18天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
38 3
|
1月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
53 5
|
1月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
111 5
|
1月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
1月前
|
算法 Java 程序员
Map - TreeSet & TreeMap 源码解析
Map - TreeSet & TreeMap 源码解析
34 0
|
1月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
67 0
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
54 0
|
1月前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
60 0

推荐镜像

更多