源码分析ThreadLocal及其应用

sysrepo 开发者指南(一个基于libyang与支持rpc的数据库) sysrepo 开发者指南(一个基于libyang与支持rpc的数据库) 日志记录 默认情况下,所有 Sysrepo 日志记录都处于关闭状态。如果启用,日志消息有 3 种输出。它们可以写入stderr、由 处理syslog或简单地传递给回调。 请务必注意,启用 Sysrepo 日志记录也会修改libyang日志记录设置。错误消息被视为标准 Sysrepo 错误,其他严重性较低的消息完全隐藏。要更改此行为,只需在启用 Sysrepo 日志记录后调整libyang日志记录设置。 此外,几乎每个 Sysrepo 阅读详情

ThreadLocal用于保存某个线程共享变量,对于同一个ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。

源码分析

核心方法:

1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。

2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。

3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。

4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。

先看看源码ThreadLocal:

//由类的定义可以看出,这里传进去了一个泛型,这里代表ThreadLocal中所操作的数据可以是任何类型
public class ThreadLocal<T> {

		//默认构造方法
	    public ThreadLocal() {
    	}
    	//初始值为空,使用时可以重写该方法
		protected T initialValue() {
      	  return null;
    	}

		//这里创建初始值,ThreadLocalMap是在ThreadLocal中声明,在Thread中定义的一个变量,默认值为null,
		//可以看出,设置的是当前线程currentThread()的一个内部属性变量ThreadLocalMap
	    private T setInitialValue() {
	        T value = initialValue();
	        Thread t = Thread.currentThread();
	        ThreadLocalMap map = getMap(t);
	        if (map != null)
	            map.set(this, value);
	        else
	            createMap(t, value);
	        return value;
	    }
		
		//这里也是到线程currentThread()里面去取值,key为当前线程ThreadLocal
    	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();
   		 }
		
		//c这里也是到线程currentThread()里面设置,key为当前线程ThreadLocal
	   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 void remove() {
	        ThreadLocalMap m = getMap(Thread.currentThread());
	        if (m != null)
	            m.remove(this);
	    }

		//创建,这个方法是在当前线程第一次储存变量的时候调用
	    void createMap(Thread t, T firstValue) {
	        t.threadLocals = new ThreadLocalMap(this, firstValue);
	    }
		
		//获取,默认Thread中ThreadLocalMap threadLocals = null
	    ThreadLocalMap getMap(Thread t) {
	        return t.threadLocals;
	    }
}

Thread 中ThreadLocalMap 定义如下:

	public class Thread implements Runnable {
    	ThreadLocal.ThreadLocalMap threadLocals = null;
    }

这里不难看出:

  • 这里当前线程中有一个ThreadLocalMap threadLocals属性的东西,用来存储当前线程的私有数据。
  • ThreadLocal的实例代表了一个当前线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。

现在唯一不了解的就是 ThreadLocal中定义的ThreadLocalMap数据结构。下面来看看:

public class ThreadLocal<T> {

	//当前ThreadLocal存储在ThreadLocalMap数组中的坐标位置,通过hash值及相关算法生成
	private final int threadLocalHashCode = nextHashCode();

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

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
		//ThreadLocalMap 实际存储数据的数组
		private Entry[] table;
		//初始容量
		private int size = 0;
		
		//获取ThreadLocal
		private Entry getEntry(ThreadLocal<?> key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }
	}

	......
}

由以上大致可以分析出:

  • ThreadLocalMap 用来管理 ThreadLocal,
  • ThreadLocalMap 数据结构为一个不连续的数组。

所以,综上就连起来了,ThreadLocal为当前线程Thread的私有数据,Thread通过可变数组ThreadLocalMap来管理ThreadLocal。开发者可以直接通过ThreadLocal来操作当前线程的私有数据。

应用

多数据源的应用场景,主要针对跨多个MySQL实例的情况。利用 注解 + AOP + ThreadLocal来实现,这里给出应用到ThreadLocal的部分如下:


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 动态数据源
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

    public static void clearDataSource() {
        contextHolder.remove();
    }

}
从零到一:TI AWR1843 Boost EVM与DCA1000 EVM的ADC数据采集实战指南 本文详细介绍了TI AWR1843 Boost EVM与DCA1000 EVM的ADC数据采集实战指南,涵盖硬件连接、软件配置、固件烧录、雷达参数设置及数据处理等关键步骤。通过MATLAB等工具,开发者可高效实现毫米波雷达数据采集,适用于自动驾驶、工业检测等领域。 阅读详情

相关推荐

SAP 分期付款,付款条件的要件定义方法

以上内容做好后,可以在F-02或者F-60里看设置后的结果。找到相关路径选择【维护支付条件】点击进入后,选择【新条目】再设置一个总的支付规则,注意这里【付款条款】一定要选择。例:默认付款条件SP00,改成刚定义好的0028即可。将刚才基础创建的付款条件,以以下方式录入,注意。028A- 30天到期,过账日期基础。028B- 60天到期,过账日期基础。028C- 90天到期,过账日期基础。目的:新建支付条款(本次以。的选择,然后保存后,完成。,【基准日期缺省值】选择。基础创建好了以后,选择【

晴天的博客分享技术知识 2936

ThreadLocal详解,源码级的详解,快来学

先看一下的官方解释。我们可以通过实例隐式地给线程设置局部变量,即该实例可以在每一个线程内部创建一个变量的副本。而该实例我们就可以通过全局共享变量的方式创建。如下图所示很多文章中将解释为多线程环境中保证线程安全的一个类,但这种说法其实是十分片面的。从官方解释上来看,的功能仅仅是为了给多个线程设置局部变量,这和线程安全是没有关系的,线程安全针对的是全局的共享变量。从类路径来看,位于java.lang包,而非包。从其使用方法来看,无论是set()方法、get()方法、remove()方法,都。

理想万岁万万岁的博客 760

QGC二次开发实战指南(一):从零构建自定义地面站界面

本文详细介绍了QGC二次开发实战指南,从零开始构建自定义地面站界面。通过QT和QML技术结合MAVLINK协议,开发者可以打造适合特定业务场景的无人机监控系统,提升操作效率与用户体验。文章包含环境搭建、界面设计、数据绑定等完整开发流程,是QGC二次开发的实用教程。

weixin_28693683的博客 496

ThreadLocal 实战应用

在 Spring 项目中 Dao 层中装配的 Connection 肯定是线程安全的,其解决方案就是采用 ThreadLocal 方法,当每个请求线程使用 Connection 的时候, 都会从 ThreadLocal 获取一次,如果为 null,说明没有进行过数据库连接,连接后存入 ThreadLocal 中,如此一来,每一个请求线程都保存有一份 自己的 Connection。每个线程的 ThreadLocalMap 是属于线程自己的,ThreadLocalMap 中维护的值也是属于线程自己的。

Stone.鱼儿的博客 1480

LangChain实战:用FAISS搭建本地文档问答系统(含Word文件处理避坑指南)

本文详细介绍了如何利用LangChain框架和FAISS向量数据库构建本地化智能文档问答系统,特别针对Word文档处理中的技术难点提供实用解决方案。通过模块化设计、本地化支持和多格式兼容,实现高效文档处理与精准问答,满足企业对数据隐私和安全的需求。

o4p5q6r7s的博客 408

新能源场站必看:一次调频与AGC/AVC的协同控制逻辑解析(含典型拓扑图)

本文深度解析了新能源场站中一次调频与AGC/AVC的协同控制逻辑。针对电网频率与电压稳定需求,详细阐述了三者在响应时序、控制目标上的分工与配合,并重点剖析了以RCL-0923装置为核心的指令融合架构与典型拓扑,为场站实现高效、稳定的协同运行提供了清晰的实践指导。

brown的博客 1059

并发编程----------线程中的共享与协作

线程中的共享与协作 线程中的共享 synchronized内置锁 线程开始运行,拥有自己的栈空间,就如同一个脚本一样,按照既定的代码一步一步的执行,直到终止。但是,每个运行中的线程,如果仅仅是孤立的运行,那么没有一点儿价值,或者说价值很少,如果多个线程能够相互配合完成工作,包括数据之间的共享,协同处理事情。这将会带来巨大的价值。 Java支持多个线程同时访问一个对象或者对象的成员变量,关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一时刻,只能有一个线程处于方法

weixin_43224466的博客 204

YOLOv11改进策略【损失函数篇】| arXiv2025 TeLU双曲正切指数线性单元 强梯度防消失 + 解析光滑稳训练,极速提升收敛与泛化

本文记录的是。TeLU(Hyperbolic Tangent Exponential Linear Unit)通过。本文利用TeLU激活函数,以x⋅tanhex统一实现正区间强梯度加速收敛与负区间持续梯度避免死神经元,全程保持解析光滑与极低计算开销,,显著提升深度网络在分类、检测、分割、时序任务中的收敛速度、精度与泛化鲁棒性。

Limiiiing的博客 224

ThreadLocal使用及源码深度解析

ThreadLocal的作用主要是做数据隔离,填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的,在多线程环境下,可以防止自己的变量被其它线程篡改。 会用在什么场景? 1.Spring实现事务隔离级别的源码 Spring采用Threadlocal的方式,来保证单个线程中的数据库操作使用的是同一个数据库连接,同时,采用这种方式可以使业务层使用事务时不需要感知并管理connection对象,通过传播级别,巧妙地管理多个事务配置之间的切换,挂起和恢复。 Spring框架里面就是用的ThreadLoca

weixin_46200547的博客 444

深入解析逆时偏移(RTM)算法及其在C++中的实现

逆时偏移(Reverse Time Migration, RTM)是一种高级地震成像技术,广泛应用于地震勘探中。RTM通过逆时传播波场来构建地震子波,能够提供更高分辨率和更精确的地下构造图像。本文将详细介绍RTM的基本原理,并通过C++代码示例,深入解析如何实现和优化RTM算法。希望这篇文章能够为地球物理学家和C++开发者提供有价值的参考。

qq_38334677的博客 1526

python全栈入门到实战【基础篇 03】入门实操:第一个Python程序 + PyCharm使用 + 输入输出全解析

本文是一篇Python入门教程,主要介绍PyCharm编辑器的安装配置和基础使用,以及Python输入输出语法的实操练习。文章分为四个部分:1)PyCharm的下载安装与基础配置;2)第一个Python程序"Hello World"的编写与运行;3)Python输入输出函数print()和input()的详细讲解;4)个人信息录入系统的实战案例。教程包含大量截图和动图演示,适合Python新手跟随操作,快速掌握编辑器使用和基础语法。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 4018

threadlocal应用及其源码分析

ThreadLocal是什么? 简单来讲就是线程局部变量,线程之间操作的变量互不影响各自独立,但如果ThreadLocal存放的是一个全局共享的引用变量依旧会有线程安全问题,ThreadLocal只是将共享变量变成私有变量达到线程安全而已 ThreadLocal的使用 public class ThreadLocalTest01 { private final static Thread...

fangzuo的专栏 164

2023年全国城市房价分布网格数据

本文介绍了一份2023年全国主要城市房价分布的网格数据,数据以250米×250米的网格为单位,记录了住宅小区数量、均价、最高价和最低价等信息。数据采用GCJ-02坐标系,提供ShapeFile、GeoJSON和CSV三种格式

J_Giser的博客 375

ThreadLocal源码分析及其应用

ThreadLocal在很多地方都有使用过,今天看看它是如何来实现的。还是先通过一个小的例子看看用法,然后再分析其源码。import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * * ThreadLocal用法示例 * */ class ThreadTask i...

高福来 188

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

threadlocal 要不要static_一文搞懂 ThreadLocal 原理

当多线程访问共享可变数据时,涉及到线程间同步的问题,并不是所有时候,都要用到共享数据,所以就需要线程封闭出场了。数据都被封闭在各自的线程之中,就不需要同步,这种通过将数据封闭在线程中而避免使用同步的技术称为线程封闭。本文主要介绍线程封闭中的其中一种体现:ThreadLocal,将会介绍什么是 ThreadLocal;从 ThreadLocal 源码角度分析,最后介绍 ThreadLocal 的应用...

weixin_39571938的博客 1435

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

通过查看ThreadLocal的源码进行简单理解

在多线程下,如果同时修改公共变量可能会存在线程安全问题,JDK虽然提供了同步锁与Lock等方法给公共访问资源加锁,但在高并发的场景下,如果多个线程争抢一把锁会出现大量的锁等待时间,让系统的响应时间变慢。对set方法中进行断点查看,当线程a第一次执行set时,先获取ThreadLocalMap对象是否为空,如果为空,那么执行createMap方法,将当前线程与需要存储的值作为参数传递。在get方法中,获取当前线程以及线程中的map对象,从对象中根据key获取存储的值并返回。

zmbwcx的博客 679

ThreadLocal的源码解析以及内存泄漏的原理分析

详细介绍了Java中的ThreadLocal的作用、原理、源码以及应用,并且介绍了ThreadLocal的内存泄漏的原理以及解决办法。

终生学习践行者 2949

Java中ThreadLocal详解(一篇就够了)

前言 ThreadLocal直译为线程局部变量,或许将它命名为ThreadLocalVariable更为合适。其主要作用就是实现线程本地存储功能,通过线程本地资源隔离,解决多线程并发场景下线程安全问题。 ThreadLocal 接下来,通过ThreadLocal的使用案例、应用场景、源码分析来进行深层次的剖析,说明如何避免使用中出现问题以及解决方案。 使用案例 前面提到关于ThreadLocal.........

starsray的博客 1万+

【Java笔记】ThreadLocal入门

ThreadLocal

小新的博客 776

Java(面试必备):面试中的 ThreadLocal 原理和使用场景

面试中的 ThreadLocal 原理和使用场景 前言 今天博主将为大家分享Java(面试必备):面试中的 ThreadLocal 原理和使用场景,不喜勿喷,如有异议欢迎讨论! 相信大家在面试中经常被问过 ThreadLocal 的原理和用法,虽然一直知道这个东西的存在但是一直没有好好的研究一下原理,没有自己的知识体系。今天安利一波有待提高 ThreadLocal 是什么 ThreadLoca...

Mr_chen的博客 1万+

初探ThreadLocal

一、ThreadLocal是干什么的 ThreadLocal是用来在多线程时存储线程内部的局部变量,各个线程之间的变量是独立的不会相互影响。(个人理解为以当前线程为key,以变量为value存储变量) 二、基本使用 空参构造,创建ThreadLocal对象。 public void set(T value)设置当前线程绑定的局部变量 public T get()获取当前线程绑定的局部变量 public void remove() 移除当前线程绑定的局部变量 protected T initialValue(

weixin_45129136的博客 294

揭秘“ThreadLocal"

引导语 ThreadLocal也是线程安全的一种措施,有这么一个经典的比喻“人手一只笔”,如果有100个人要签名,只有一支笔的话,那么肯定要排起长队了,但如果准备了100支笔,那就可以做到每人一支笔啦。 ThreadLocal的官方解释:线程局部变量,是一个以ThreadLocal对象为键,任意对象为值得存储结构,这个结构倍附带在线程上,也就是说一个线程可以根据一个ThreadLocal对象查...

一不小心吃太撑了 878

java并发——深入理解ThreadLocal

通过本文你将了解到如下内容 ThreadLocal的用途、场景 常见的实际应用场景 使用ThreaLocal所带来的好处 ThreadLocal原理剖析 主要方法介绍 ThreadLocal源码分析 ThreadLocal使用注意点 ThreadLocal的用途 从其名字我们就可以看到ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。Thr...

毅航的博客 702

简析ThreadLocal

ThreadLocal是什么 我们知道在使用多线程时,有时需要共享变量,需要同步数据,所以各个线程之间对这个变量都是开放的,这概念可以称之为线程开放。但也不是所有时候都需要同步数据,每个线程也可以有自己独有的变量,不需要同步给其他线程,这概念可以叫做线程封闭。而ThreadLocal就是线程封闭具体的体现之一。在JDK1.2版本里就提供了java.lang.ThreadLocal类,我们可以把...

硅脂味咖啡的博客 474

Java并发编程:深入剖析ThreadLocal

想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。  以下是本文目录大纲:  一.对ThreadLocal的理解  二.深入解析ThreadLocal类  三.ThreadLocal的应用场

瓜爪牛的博客 218

深入理解线程本地变量ThreadLocal

ThreadLocal理解:如果在多线程并发环境中,一个可变对象涉及到共享与竞争,那么该可变对象就一定会涉及到线程间同步操作,这是多线程并发问题。否则该可变对象将作为线程私有对象,可通过ThreadLocal进行管理,实现线程间私有对象隔离的目的。可以发现,ThreadLocal并没有解决多线程并发的问题,因为ThreadLocal管理的可变对象的性质本来就不会涉及到多线程并发而引发的共享、竞争和同

javaloveiphone的专栏 5239

Java并发编程之ThreadLocal源码分析

1 一句话概括ThreadLocal   什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象的线程创建了一个独立的变量副本。 2 ThreadLocal使用场景   用一句话总结ThreadLocal真的实在是太苍白无力了!我们通过一个简单的例子入手。比如现在有A和B两台服务器需要通过http请求传递数据,但又希望数据安全性有一定保障,因此发送方A决定用AES算法对传输数据加...

weixin_30900589的博客 155
上一篇: SpringBoot中WebMvcConfigurer接口详解
下一篇: oracle使用日常总结
She_lock
博客等级 码龄12年 157粉丝 134原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值