ThreadLocal的一些自己的理解

理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 立即下载



有关于ThreadLocal的原理的源代码解释在下面已经说的很清楚了 源代码也很清晰易懂

http://www.cnblogs.com/dolphin0520/p/3920407.html



个人对于ThreadLocal类的一些总结:

1.

ThreadLocal类并不是将线程和所存储的对象进行键值保存的和进行取值的(这是我第一反应以为的)

而是将存储的值保存到对应Thread对象的ThreadLocalMap里,ThreadLocalMap的实现原理类似于hashMap,

内部有一个Entry数组,一个Entry通常至少包括key,value, 查找时通过一定的运算规则运算Key的HASH值,来得到Entry在数组中的位置,进而得到相应的value。

但是这个ThreadLocalMap是将当前ThreadLocal对象实例传入当作键值,将set的对象当value值进行存储

下面是ThreadLocal的set方法源码

  public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);//将this传入 
        else
            createMap(t, value);
    }


我们进map的set里看看

  private void set(ThreadLocal key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);//对key进行hash运算 存储

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }


取值时也根据对应的thread对象拿出自己的threadLocalMap,再根据threadLocal的实例为键值得到对应本线程本ThreadLocal的副本

   public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }


2

每个threadLocalMap对应每个线程只能存储一个对象

也就是说你set了一个对象A,再放入对象B ,对象B就会把对象A取代 这就跟HashMap一样 

因为ThreadLocal是键值.。通过以上的代码也能看出来 



3.

先看一段代码

public class Test
{
	public int i = 1;
	static ThreadLocal<Object> t =  new ThreadLocal<Object>();
	public static void main(String[] args){
		Test test = new Test();
		Test test1 = new Test();
		MyThread m1= new MyThread(2,test,true);
	//	MyThread m2 = new MyThread(3,test1,false);
		MyThread m2 = new MyThread(3,test,false);
		Thread t1 = new Thread(m1);
		Thread t2 = new Thread(m2);
		t1.start();
		t2.start();

	}
}

class MyThread implements Runnable{
	int obj;
	boolean  flag;
	Test t;
	public MyThread(int i,Test t ,boolean flag){
		this.obj = i;
		this.t=t;
		this.flag=flag;
	}
	
	@Override
	public void run()
	{
		Test.t.set(obj);//该放入的对象被后面的所取代
		Test.t.set(t);//只在run期间threadLocals是保存的 run之后threadLocals置空
		//并不是由threadLocal给你克隆 副本 而是由你自己来设置放进去的副本
		
		Test t = (Test) get();
		if(flag==false){
			try
			{
				Thread.sleep(5000);//睡眠 确保另外一个线程已经操作结束
			} catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("线程为"+Thread.currentThread().getId()+"原来的:"+t.i);
		t.i = obj;//改变值
		System.out.println("线程为"+Thread.currentThread().getId()+"现在的:"+((Test)get()).i);
		System.out.println("线程为"+Thread.currentThread().getId()+"所存储的对象:"+get());
	
	}
	
	public Object get(){
		return Test.t.get();
	}
	
}



此时输出如下:

线程为9原来的:1
线程为9现在的:2
线程为9所存储的对象:ThreadLocalTest.Test@65b8b5cd
线程为10原来的:2
线程为10现在的:3
线程为10所存储的对象:ThreadLocalTest.Test@65b8b5cd


我在两个线程放入了同一个Test对象test,当然run方法里也set了这个test

像我刚开始以为ThreadLocal会自动为每个线程创建一个副本(好可笑的梦哈)

这段代码也证实了并不会。

所以并不是由ThreadLocal给你克隆副本,而是由你自己来设置放进去的副本


如果将注释的代码代替

则输出如下:


线程为9原来的:1
线程为9现在的:2
线程为9所存储的对象:ThreadLocalTest.Test@65b8b5cd
线程为10原来的:1
线程为10现在的:3
线程为10所存储的对象:ThreadLocalTest.Test@72d2ee5d


上面啰嗦一大堆 就是为了让我自己认识到ThreadLocal需要自己来设置对应每个线程的副本

而这就需要执行ThreadLocal的set方法 或者重写ThreadLocal的initialValue方法

如同下面这样:

static ThreadLocal<Object> t =  new ThreadLocal<Object>(){
		public Object initialValue(){
			return new Test();
		}
	};




Anolis OS 23实战:5分钟搞定AI环境配置(含NVIDIA驱动一键安装) 本文详细介绍了如何在Anolis OS 23上快速配置AI开发环境,包括NVIDIA驱动的一键安装和TensorFlow、PyTorch等AI框架的部署。通过智能硬件适配引擎和优化后的二进制包,用户可在5分钟内完成传统需要数小时的配置工作,显著提升AI项目开发效率。 阅读详情

相关推荐

ur3手眼标定+realsenseL515

知乎 csdn

AI_future的博客 976

ThreadLocal详解

这几天看《Java并发编程之美》的时候又遇到了这个类,不得不说,这个类在平时很多场景都遇得到,所以对其进行一个系统性的学习,然后再输出成这篇博客。 那么,什么是ThreadLocal呢? 我们都知道,多线程访问同一个共享变量很容易出现并发问题,特别是当多个线程对同一个共享变量进行写入操作时。一般为了避免这种情况,我们会使用这个关键字对代码块加锁。但是这种方式一是会让没获取到锁的线程进行阻塞等待,二是需要使用者对锁有一定的了解,无疑提高了编程的难度。其实ThreadLocal 就可以做这件事情,虽然Threa

apple_52109766的博客 2568

Windows 11下ROS2 Humble与PyCharm无缝集成实战(避坑指南+完整配置流程)

本文详细介绍了在Windows 11系统下如何实现ROS2 Humble与PyCharm的无缝集成,包括环境准备、ROS2 Humble安装、PyCharm配置以及C++与Qt5混合开发的实战技巧。通过避坑指南和完整配置流程,帮助开发者高效搭建稳定的机器人开发环境,特别适合Windows平台的ROS2开发者。

weixin_28710999的博客 366

深度解析ThreadLocal

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

worn_xiao的博客 530

CD-HIT的使用

继续我的生信笔记系列。从某网站的附带文献中读到该工具,搜索了一下,发现网上的大佬们都在讲如何用它去冗余,相对官方页面的介绍而言很是片面,于是刚好有聚类的需求的我准备对其全体功能做做实验,学习一下由李伟忠博士在伯纳姆研究所(现为桑福德伯纳姆医学研究所)亚当·戈兹克博士的实验室开发的牛工具。 首先是官方介绍: CD-HIT是一个非常广泛使用的程序,用于蛋白质或核苷酸序列的聚类和比较。最初由李伟忠博士在伯纳姆研究所(现为桑福德伯纳姆医学研究所)亚当·戈兹克博士的实验室开发,CD-HIT速度非常快,可以处理非常

一名学术waste的note pro 1万+

【R语言实例】物种分布模型介绍

SDM介绍

wong2016的博客 1万+

ThreadLocal 详解

ThreadLocal 概述 ThreadLocal类用来提供线程内部的局部变量,不同的线程之间不会相互干扰 这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量 在线程的生命周期内起作用,可以减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度 使用 常用方法 方法名 描述 ThreadLocal() 创建ThreadLocal对象 public void set( T value) 设置当前线程绑定的局部变量 publ

ant的博客 2万+

解决Android UVCCamera stopPreview 报错 崩溃 闪退 问题

在使用libuvccamera库的UVCCamera时,经常在调用stopPreview关闭预览的时候,app直接崩溃闪退了,经过综合各种修改源码的方案,已解决这个问题,以下请参考: 首先找到android_usbfs.c,linux_usbfs.c两个原文件,在两个文件中都可以找到这段代码,按如下示例修改: 修改前: for (i = 0; i < num_urbs; i++) { if (urb == tpriv->iso_urbs[i]) { urb_idx = i + 1;

hanye2020的博客 3576

责任链模式--值的传递方式

在使用责任链模式时,有的时候需要在某一些链点上传出值,在调用链路的方法中使用中间的值。方式一:在方法中直接返回,这样每个点的返回值就不统一,抽象方法就比较乱。方式二:在方法中的参数传入一个对象。方式三:使用ThreadLocal进行值传递。责任链模式-数据传递。

super_lyj的博客 801

FPGA电路设计2——芯片原理图绘制

FPGA板卡设计要点:1. 引脚分配遵循电平标准分组原则,需通过预编译验证;2. 电源设计需满足上电时序要求并合理估算功耗;3. 最小系统包含配置Bank(Bank0)、通用I/O Bank(HRBank)、高性能Bank(HPBank)和高速收发器Bank(MGT/GTX)。其中Bank0负责关键配置功能,包括模式选择(支持SPI/BPI/JTAG等5种配置方式)、JTAG调试接口和系统监控引脚,其电压选择(CFGBVS_0)必须与VCCO_0电压匹配。

在读研究生,FPGA电路设计与功能开发。 1235

【图像超分】论文精读:Accelerating the Super-Resolution Convolutional Neural Network(FSRCNN)

作为应用于图像超分辨率 (SR) 的成功深度模型,超分辨率卷积神经网络 (SRCNN) [1,2] 在速度和恢复质量方面都比以前的手工制作的模型表现出更好的性能。然而,高计算成本仍然阻碍了它的实际使用,这需要实时性能(24 fps)。在本文中,我们旨在加速当前的 SRCNN,并提出了一种紧凑的沙漏形 CNN 结构,以实现更快和更好的 SR。我们从两个方面重新设计了SRCNN结构。首先,我们在网络末端引入了一个反卷积层,然后将映射直接从原始低分辨率图像(无插值)学习到高分辨率图像。其次,我们通过在映射之前缩小

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 1万+

threadlocal理解

threadlocal理解

qq_37021992的博客 244

Android 12.0 系统systemui状态栏下拉左滑显示通知栏右滑显示控制中心模块的流程分析

在android12.0的系统rom定制化开发中,在系统原生systemui进行自定义下拉状态栏布局的定制的时候,需要在systemui下拉状态栏下滑的时候,根据下滑坐标来 判断当前是滑出通知栏还是滑出控制中心模块,所以就需要根据屏幕宽度,来区分x坐标值为多少是左滑出通知栏或者右滑出控制中心模块,接下来分析下 状态栏下滑坐标等相关功能代码分析

安卓兼职framework和app工程师的博客 2768

ThreadLocal理解

1.ThreadLocal介绍ThreadLocal可以理解为是线程的本地变量,它为每个线程都创建一个副本。线程通过set\get操作访问内部副本变量,实现了线程之间的隔离。2.ThreadLocal与synchronized区别3.ThreadLocal设计在JDK8中ThreadLocal的设计是每一个Thread都维护一个ThreadLocalMap,这个Map的key就是ThreadLocal实例本身,value才是真正要存储的值。 每个Thread内部维护一个ThreadLocalMap,map里

dream_loverm的博客 797

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

对于ThreadLocal的理解

在Java的多线程并发执行的过程中,为了保证多个线程对变量的安全访问,可以将变量放到ThreadLocal类型的对象中,是变量在每一个线程中都有独立的值,不会出现一个线程读取变量时被另一个线程修改的现象。ThreadLocal类通常被翻译为本地变量类或者线程局部变量。ThreadLocal位于JDK的java.lang核心包中。如果程序创建了一个ThreadLocal实例,那么在访问这个变量的值时,每个线程都会拥有一个独立的、自己的本地值。

天青色 等烟雨的博客 537

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ThreadLocal 的个人理解

之前看了一些ThreadLocal的源码理解,小总结,有错误忘指出! ThreadLocal,即一个线程变量,是一个以ThreadLocal对象为键,任意对象为值的存储结构。 ThreadLocal类中有一个名为ThreadLocalMap的内部类,该内部类中有一个Entry[] table的数组,每一个Entry存放一个键值对(ThreadLocal对象为键,任意对象为值)。 Threa...

zzlhcm的博客 183

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

ThreadLocal的理解

自己对ThreadLocal的一点理解

weixin_65494348的博客 1909

ThreadLocal的理解与应用

在平时java开发中,如果想使用共享变量,往往使用public static 的方式修饰一个类的成员变量,这样就能实现变量共享了。不过,这样的变量是所有线程都共享的,有没有什么方式可以让这个变量只在某个线程中共享使用呢,答案是有的,可以使用ThreadLocal来解决这个问题。 一、ThreadLocal简介 hreadLocal类并不是用来解决多线程环境下的共享变量问题,而是用来提供线程内部的共享变量,在多线程环境下,可以保证各个线程之间的变量互相隔离、相互独立。在线程中,可以通过get()/set()方

Coder-文小白的博客 549

ThreadLocal的简单理解

目录* 一、背景最近有人问我是如何做到在每个线程中的值都是隔离的,此处写篇文章来简单记录下。比如:用户登录成功后,需要将保存起来,以方便在系统中的任何地方都可以使用到,那么此时就可以使用来实现。例如:中的类。 ThreadLocal的实例推荐使用来修饰。 :这个是线程类,在这个类中存在一个变量,具体的类型是。 2、看下set方法是如何实现的 通过上方的代码,我们可知: 当我们向ThreadLocal中设置一个值,会经过如下几个步骤: 五、ThreadLocalMap中的hash冲突是如何处理的 1、

xuhss_com的博客 174

ThreadLocal源码理解

前言 在之前的工作和学习中比较少涉及到ThreadLocal的使用,直到学习Handle消息机制时,在Looper类中使用了ThreadLocal,于整个Handle机制而言ThreadLocal的意义还是很重要的,在后来的某条面试中也被问到过,也证明ThreadLocal是有必要学习一下的。 private static void prepare(boolean quitAllowed) { ...... sThreadLocal.set(new Looper(quitA

qq_27246079的博客 231

ThreadLocal 的理解

ThreadLocal叫做线程变量,其中维护的变量,独属于ThreadLocal对应的线程,其他线程无法访问到ThreadLocal中的变量,所以ThreadLocal是线程安全的。ThreadLocal线程安全的原理在于,ThreadLocal会为每一个线程提供一个副本,每个线程访问的都是自己的ThreadLocal,相互隔离。一般来说ThreadLocal会被private static修饰,但如果需要在多个方法间使用,也可以放开private使用public,实现在多个方法和类中使用。

weixin_74165435的博客 1559

深入理解ThreadLocal

文章目录1、什么是 ThreadLocal2、ThreadLocal 使用案例3、ThreadLocal和 sychronized区别 1、什么是 ThreadLocal ThreadLocal类用来为线程内部提供局部变量。该变量在多线程环境下读写能保证各个线程变量独立于其他线程内的变量。不同的线程之间不会相互干扰! 总结: 线程并发:在多线程并发场景下(单线程不需要使用ThreadLocal) 传递数据:我们可以通过ThreadLocal在同一线程,不同组件中传递公共变量 线程隔离:每个线程变量都

保持学习 1549

ThreadLocal的通俗理解

在并发编程中,为了防止不同线程同时操作同一个变量,导致线程不安全,就需要将原数据中各线程需要用到的数据copy一份副本出来,放在自己的线程的“仓库”中,线程对副本进行操作,这样其他线程就不会对此进行干扰,避免不同线程争“抢修”改同一变量,这里用到的就是ThreadLocal 类。Entry是一个对象,其中存储着 ThreadLocal 对象的引用(即原始数据的类型和变量名)和该线程的 ThreadLocal 变量的副本(线程专有数据的值)

2301_80895430的博客 254

理解 ThreadLocal

理解 ThreadLocal 原来就用过ThreadLocal,但是不是特别的明白,今天又看了一下。 摘自《Spring 揭密》 王福强著 人民邮电出版社 1 ThreadLocal的背景 单单从程序层面来看,我们编写的代码实际上是在管理系统中各个对象的相关状态,如果不能对各个对象的状态的访问进行合理的管理,对象的状态将被破坏,进而导致系统的不正常运行,特别是多线程环境下,多个线程可能对系

liuliangsailor的专栏 661
上一篇: springmvc 源码学习 handlerInterceptor
下一篇: C语言实现二叉排序树的增删查操作
看风人Z
博客等级 码龄11年 13粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值