多线程-ThreadLocal

关于ThreadLocal的那点事 ThreadLocal是什么 ThreadLocal类提供线程内部的局部变量,在多线程环境(即多线程并发场景)访问时能够保证变量相对独立于其他线程内的变量(即线程隔离),用于关联线程和线程上下文(意味着可以通过ThreadLocal在同一线程下,不同的组件里传递共用变量)。 @Data public class ThreadDemo2 { private ThreadLocal<String> tl = new ThreadLocal<>(); public sta 阅读详情

#前言

面试多线程好像必不可少的一个知识点
是什么?有什么用?应用场景?

ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型,不允许外部修改。 它和线程同步是相反的作用,以实现每个线程内的变量都是独自分开的,互不影响。

ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程可以创建一个或者多个ThreadLocal,ThreadLocal本身不是什么对象的拷贝或副本。核心在于Thread类本身就包含一个定义了的ThreadLocal.ThreadLocalMap类型的threadLocals。

注意

ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set()
到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

#线程局部变量

使用场景
在多线程环境下,之所以会有并发问题,就是因为不同的线程会同时访问同一个共享变量,例如下面的形式,模拟多线程下局部变量的修改问题:

public class MultiThreadDemo {

    public static class Number {
        private int value = 0;

        public void increase() throws InterruptedException {
            value = 10;
            Thread.sleep(10);
            System.out.println("increase value: " + value);
        }

        public void decrease() throws InterruptedException {
            value = -10;
            Thread.sleep(10);
            System.out.println("decrease value: " + value);
        }
    }

//执行多线程对局部变量进行修改操作
    public static void main(String[] args) throws InterruptedException {
        final Number number = new Number();
        Thread increaseThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    number.increase();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread decreaseThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    number.decrease();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        increaseThread.start();
        decreaseThread.start();
    }
}

increase 线程和 decrease 线程会操作同一个 number 中 value,那么输出的结果是不可预测的,因为当前线程修改变量之后但是还没输出的时候,变量有可能被另外一个线程修改

在多线程中如何保证数据的原子性呢,当然我们可以在方法上使用同步synchronized,这样就成为了同步代码,显然在性能上有影响,我们要

#ThreadLocal的接口方法
ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

  • void set(Object value)

  • public void remove()
    将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 1.5 新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。

  • protected Object initialValue()
    返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。
    值得一提的是,在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。

  • T get()

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中定义了一个ThreadLocalMap,每一个Thread中都有一个该类型的变量——threadLocals——用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。

通过源码可以看出每个

 public void set(T value) {
 //所有设置的数据都以当前主线程的hashcode为标识,所以只要线程不同它的变量threadLocals就不会相同
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);// 获取当前主线程的threadLocals,它是一个map类型,所以可以存放多个值,key是以当前变量ThreadLocal类型为key值加以区分
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);//如果发现threadLocals是初始值null则把主线程的变量threadLocals新建一个,并把当ThreadLocal变量-值作为键值对保存进去
    }
    
 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);//获取当前主线程的threadLocals
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//获取当前ThreadLocal变量为key的值
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

参考源码资料https://www.cnblogs.com/dolphin0520/p/3920407.html

#应用场景

##hibernate中的使用
下面来看一个hibernate中典型的ThreadLocal的应用:
每次获取的都是自己的session,而不是共享的session

private static final ThreadLocal threadSession = new ThreadLocal();  
  
public static Session getSession() throws InfrastructureException {  
    Session s = (Session) threadSession.get();  
    try {  
        if (s == null) {  
            s = getSessionFactory().openSession();  
            threadSession.set(s);  
        }  
    } catch (HibernateException ex) {  
        throw new InfrastructureException(ex);  
    }  
    return s;  
}  

可以看到在getSession()方法中,首先判断当前线程中有没有放进去session,如果还没有,那么通过sessionFactory().openSession()来创建一个session,再将session set到线程中,实际是放到当前线程的ThreadLocalMap这个map中,这时,对于这个session的唯一引用就是当前线程中的那个ThreadLocalMap(下面会讲到),而threadSession作为这个值的key,要取得这个session可以通过threadSession.get()来得到,里面执行的操作实际是先取得当前线程中的ThreadLocalMap,然后将threadSession作为key将对应的值取出。这个session相当于线程的私有变量,而不是public的。

显然,其他线程中是取不到这个session的,他们也只能取到自己的ThreadLocalMap中的东西。要是session是多个线程共享使用的,那还不乱套了。

试想如果不用ThreadLocal怎么来实现呢?可能就要在action中创建session,然后把session一个个传到service和dao中,这可够麻烦的。或者可以自己定义一个静态的map,将当前thread作为key,创建的session作为值,put到map中,应该也行,这也是一般人的想法,但事实上,ThreadLocal的实现刚好相反,它是在每个线程中有一个map,而将ThreadLocal实例作为key,这样每个map中的项数很少,而且当线程销毁时相应的东西也一起销毁了,不知道除了这些还有什么其他的好处。

##日志记录

计算当前线程的方法运行时间

/**
 * zjcjava@163.com
 */

/**
 * 系统日志拦截器:需要在springMVC中配置
 * @author zjcjava@163.com
 * @version 2017-8-19
 */
public class SysLogInterceptor extends BaseService1 implements HandlerInterceptor {

	private static final ThreadLocal<Long> startTimeThreadLocal =
			new NamedThreadLocal<Long>("ThreadLocal StartTime");

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
			Object handler) throws Exception {
		long beginTime = System.currentTimeMillis();//1、开始时间  
        startTimeThreadLocal.set(beginTime);		//线程绑定变量(该数据只有当前请求的线程可见)  
		if (logger.isDebugEnabled()){
	        logger.debug("开始计时: {}  URI: {}", new SimpleDateFormat("hh:mm:ss.SSS")
	        	.format(beginTime), request.getRequestURI());
		}
		
	
		
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
			ModelAndView modelAndView) throws Exception {
		if (modelAndView != null){
			logger.info("ViewName: " + modelAndView.getViewName());
		}
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
			Object handler, Exception exception) throws Exception {

		Long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)  
		if(beginTime==null){
			beginTime=System.currentTimeMillis(); 	
		}
		
		long endTime = System.currentTimeMillis(); 	//2、结束时间 
		double executeTime =(double)(endTime - beginTime)/1000;//秒
		SysLog log=sysLogThreadLocal.get();
		log.setExecuteTime(executeTime);
		log.setType(exception == null ?SysLog.TYPE_ACCESS :SysLog.TYPE_EXCEPTION);
		// 保存日志
		SysLogUtils.saveLog(log, handler, exception);

	        //删除线程变量中的数据,防止内存泄漏
	        startTimeThreadLocal.remove();
		}
		
	}

}

在拦截器中每个线程都可以在进入方法前保存当前时间戳,方法运行完后计算总共的运行时长。其他线程是无法修改该开始时间的。

#实现原理

ThreadLocal
这里写图片描述
ThreadLocal的实现是这样的:每个Thread 维护一个 ThreadLocalMap 映射表,这个映射表的 key 是 ThreadLocal实例本身,value 是真正需要存储的 Object。

也就是说 ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value。值得注意的是图中的虚线,表示 ThreadLocalMap 是使用 ThreadLocal 的弱引用作为 Key 的,弱引用的对象在 GC 时会被回收。

看源码

public T get() {
    Thread t = Thread.currentThread();//当前线程
    ThreadLocalMap map = getMap(t);//获取当前线程对应的ThreadLocalMap
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);//获取对应ThreadLocal的变量值
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();//若当前线程还未创建ThreadLocalMap,则返回调用此方法并在其中调用createMap方法进行创建并返回初始值。
}
//设置变量的值
public void set(T value) {
   Thread t = Thread.currentThread();
   ThreadLocalMap map = getMap(t);//默认以当前线程的实例作为KEY值
   if (map != null)
       map.set(this, value);
   else
       createMap(t, value);
}

/**
为当前线程创建一个ThreadLocalMap的threadlocals,并将第一个值存入到当前map中
@param t the current thread
@param firstValue value for the initial entry of the map
*/
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
//删除当前线程中ThreadLocalMap对应的ThreadLocal
public void remove() {
       ThreadLocalMap m = getMap(Thread.currentThread());
       if (m != null)
           m.remove(this);
}

看 set(T value) 方法Thread t = Thread.currentThread()以当前线程的实例作为map中的KEY,
总之,为不同线程创建不同的ThreadLocalMap,用线程本身为区分key,每个线程之间其实没有任何的联系,说是说存放了变量的副本,其实可以理解为为每个线程单独new了一个对象放到map中。

##ThreadLocalMap

开放定址法不会创建链表,当关键字散列到的数组单元已经被另外一个关键字占用的时候,就会尝试在数组中寻找其他的单元,直到找到一个空的单元。探测数组空单元的方式有很多,这里介绍一种最简单的 – 线性探测法。线性探测法就是从冲突的数组单元开始,依次往后搜索空单元,如果到数组尾部,再从头开始搜索(环形查找)。如下图所示:
这里写图片描述
ThreadLocalMap 中使用开放地址法来处理散列冲突,而 HashMap 中使用的分离链表法。之所以采用不同的方式主要是因为:在 ThreadLocalMap 中的散列值分散的十分均匀,很少会出现冲突。并且 ThreadLocalMap 经常需要清除无用的对象,使用纯数组更加方便。

实现
我们知道 Map 是一种 key-value 形式的数据结构,所以在散列数组中存储的元素也是 key-value 的形式。ThreadLocalMap 使用 Entry 类来存储数据,下面是该类的定义:

 //map中的每个节点Entry,其键key是ThreadLocal并且还是弱引用,这也导致了后续会产生内存泄漏问题的原因。
 static class Entry extends WeakReference<ThreadLocal<?>> {
           Object value;
           Entry(ThreadLocal<?> k, Object v) {
               super(k);
               value = v;
   }
    /**
     * 初始化容量为16,以为对其扩充也必须是2的指数 
     */
    private static final int INITIAL_CAPACITY = 16;
    /**
     * 真正用于存储线程的每个ThreadLocal的数组,将ThreadLocal和其对应的值包装为一个Entry。
     */
    private Entry[] table;


    ///....其他的方法和操作都和map的类似

可以看到extends WeakReference使用了弱引用,这也导致了后续会产生内存泄漏问题的原因。

#ThreadLocal内存泄漏问题(参考其他博文)
  在上面提到过,每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap. Map中的key为一个threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key. 每个key都弱引用指向threadlocal. 当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用. 只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.
  所以得出一个结论就是只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间不会被回收的,就发生了我们认为的内存泄露。其实这是一个对概念理解的不一致,也没什么好争论的。最要命的是线程对象不被回收的情况,这就发生了真正意义上的内存泄露。比如使用线程池的时候,线程结束是不会销毁的,会再次使用的。就可能出现内存泄露。

那么怎么避免内存泄漏呢?
每次使用完ThreadLocal,都调用它的remove()方法,清除数据【请参考本文使用场景:日志记录】。

内存泄漏的样例,参考
ThreadLocal 内存泄露的实例分析
http://blog.youkuaiyun.com/lhqj1992/article/details/52451136

#参考文章

参考文章
http://www.iteye.com/topic/103804
http://www.jianshu.com/p/529c03d9b67e
http://stackoverflow.com/questions/38994306/what-is-the-meaning-of-0x61c88647-constant-in-threadlocal-java
http://jerrypeng.me/2013/06/thread-local-and-magical-0x61c88647/
ThreadLocal是否会引发内存泄露的分析(转)
[Java并发包学习七]解密ThreadLocal
数据结构与算法分析: C语法描述

Android Termux 安装Kali Linux 或 kali Nethunter史诗级详细教程 Termux 安装kali 阅读详情

相关推荐

PostgreSQL中idle in transaction状态的5个隐藏危害及实战解决方案

本文深入剖析了PostgreSQL中`idle in transaction`连接状态的五大隐藏危害,包括内存与锁泄漏、VACUUM受阻导致表膨胀、事务ID加速消耗、连接池资源耗尽以及增加故障排查复杂度。文章提供了基于`pg_stat_activity`视图的监控方法、识别高危事务的SQL脚本,并给出了从数据库参数调优(如设置`idle_in_transaction_session_timeout`)到应用层编码规范与连接池配置的完整实战解决方案。

zzz56的博客 234

NamedThreadLocal和Threadlocal有什么区别?

继承和重写:NamedThreadLocal可以通过继承并重写initialValue方法来初始化变量的初始值。使用场景:NamedThreadLocal适用于需要在多个线程之间共享变量,并且需要通过名称进行访问的场景。可见性:NamedThreadLocal的变量副本在多线程之间是可见的,可以通过名称获取和设置变量值。命名:NamedThreadLocal是ThreadLocal的子类,它添加了一个名称属性,可以为每个ThreadLocal实例指定一个唯一的名称。

qq_53084097的博客 1943

同源策略与跨域

前言:最近业务上前端同学多次联系说访问腾讯云cos资源的时候因为跨域的问题访问不到。大致看了下腾讯云关于设置跨域访问的教程,按照前端同学给的域名等选项就给配了,而且测试下来也是好的。但是呢一直不知道什么是跨域这里就做一个简单的学习记录。 一、同源策略 同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全功能。同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。...

mijichui2153的博客 1万+

java多线程 ThreadLocal理论总结

目录 什么是ThreadLocal变量 使用样例 threadlocal的内部属性-哈希 ThreadLocalMap ThreadLocal 内存泄漏,remove方法 ThreadLocal 的 set 方法 ThreadLocal 的 get 方法 ThreadLocalMap 的 resize 方法 ThreadLocal 应用场景 注意:本文参考了https://baijiahao.baidu.com/s?id=1663127810801876375 什么是ThreadLoc

今天吃了吗的博客 2405

使用 Python 和可视化编程控制树莓派机械臂myCobot

这些模块包括逻辑、循环、数学、文本、列表、颜色、变量、函数以及控制机械臂的函数等等,所以用户可以轻松入门编程,只需单击右上角的运行就可以启动程序,做一些有趣的应用。可以搭配任意摄像头进行图像识别,具有4个 USB 端口,可以通过 Raspberry Pi 的微型 HDMI 端口连接到显示器. 最后,40 个GPIO 接头可以进行更多扩展应用,机械臂每个接口都有清晰的标记,面板上还有一个电源开关和一个直流电源插孔。您现在可以将机器人放在地板或桌子上,并用力拧紧吸盘,以确保机械臂的底座在操作过程中不会移动。

m0_62456998的博客 3965

Photoscan+Smart3D+CC组合建模实战:如何用三款工具打造高精度实景模型

本文详细介绍了如何整合Photoscan、Smart3D和ContextCapture三款软件,构建高效高精度的实景三维建模工作流。通过利用Photoscan稳健的空三解算、Smart3D精准的刺点优化,以及ContextCapture强大的最终建模能力,该方案能有效应对复杂地形与海量数据,显著提升模型质量与生产效率,适用于测绘、文化遗产数字化等专业领域。

weixin_29230649的博客 103

让你彻底理解ThreadLocal原理和应用

1.为什么需要ThreadLocal 我们举个生活中的例子来说明: 你带着三个孩子出去逛街,路过了玩具店,三个孩子都看中了一款变形金刚。 所以你买了一个变形金刚,打算让三个孩子轮着玩。 回到家你发现,孩子因为这个玩具吵架了,三个都争着要玩,谁也不让着谁。 这时候怎么办呢?你可以去拉架,去讲道理,说服孩子轮流玩,但这很累。 所以一个简单的办法就是出去再买两个变形金刚,这样三个孩子都有各自的变形金刚,世界就暂时得到了安宁。 映射到我们今天的主题,变形金刚就是共享变量,孩子就是程序运行的线程。 有多个线程(孩子)

qq_51443459的博客 1771

DM9000有线网卡驱动编写

DM9000有线网卡驱动编写 1.DM9000简介   DM9000 是一款完全集成的、性价比高、引脚数少、带有通用处理器接口的单芯片快速以太网控制器。 自 带一个 10/100M PHY 和 4K 双字的 SRAM ,DM9000A 为适应各种处理器提供了 8 位、16 位数据接口访问 内部存储器,DM9000 拥有自动协商功能,DM9000 特性如下:   1.集成自适应 10/100M 收发器。   2.内置 16k 字节的 SRAM。   3.支持硬件帧校验。   4.兼容 3.3V 和 5.0V

weixin_44453694的博客 4672

十分钟带你了解清楚什么是ThreadLocal

ThreadLocal

m0_62609939的博客 1246

【零基础入门unity游戏开发——3D篇】3D物理关节 —— Joint相关组件

【零基础入门unity游戏开发——3D篇】3D物理关节 —— Joint相关组件

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1198

机器学习之多种算法优缺点总结及优化方法

一、无监督算法: 1、聚类算法:Kmeans 2、关联规则算法:Apriori 二、有监督算法 1、分类算法 决策树(Decision Tree) 支持向量机(SVM) K近邻(kNN,k-NearestNeighbor) 朴素贝叶斯 逻辑回归 2、回归算法 线性回归 多项式回归 3、集成算法 a、bagging(Bootstrapped Aggregation) 随机森林 ...

平原的博客 7081

多线程中ThreadLocal详解

1. ThreadLocal是什么,是用来解决什么问题的? ThreadLocal从字面意思来理解,是一个线程本地变量,也可以叫线程本地变量存储。有时候一个对象的变量会被多个线程所访问,这个时候就会有线程安全问题,当然可以使用synchronized关键字来为该变量加锁,进行同步处理来限制只能有一个线程来使用该变量,但是这样会影响程序执行的效率,这时ThreadLocal就派上了用场; 使用T...

Helon的博客 6628

企业 IoT 产品安全渗透测试与欧盟 CRA 合规落地实战指南

欧盟 CRA(网络弹性法案)2026-09-11 漏洞报告义务生效,2027-12-11 全面强制产品安全不再是"加分项",而是市场准入的法律门槛本文面向 IoT 企业安全工程师/运维工程师,讲清楚如何从零建立渗透测试能力,并与 CRA 合规要求对齐落地。不讲空话,全是可执行的步骤。IoT 企业安全工程师、运维工程师负责产品合规的技术人员想从"被动响应"转向"主动安全"的团队[ ] 能独立完成 Web 应用渗透测试并输出报告[ ] 能对 REST/GraphQL API 进行安全评估。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 266

多线程之ThreadLocal

多线程之ThreadLocal 问题:多线程之间的数据共享,保证线程安全。 举例代码实现: public class ThreadLocalTest { private static ThreadLocal<Integer> x = new ThreadLocal<Integer>(); public static void main(String[] args) { for(int i=0;i<2;i++){ new Thread(new Runnable(

等一轮明月的博客 161

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

多线程中ThreadLocal的使用

前言 多线程是Java的一个重要特性,多线程从某方面可以等价于多任务,当你有多个任务要处理时,多个任务一起做所消耗的时间肯定比任务串行起来做,所消耗的时间短。而对于多线程不熟悉的新手则容易踩到很多坑,最典型的则是变量问题。 概念介绍 下面先用简单粗俗的语言解释一下几个基本概念 线程安全:多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。典型的例子为StringBuffer类。 线程不安全:不提供数据

qq_41530937的博客 787

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

多线程ThreadLocal

什么是多线程ThreadLoca ThreadLocal提供一个线程的局部变量,访问某个线程拥有自己局部变量。 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 简单的一句话:就是它让变量不会共享,每个线程都有各自的变量。 ThreadLoca方法如下: 1.void ...

qq_35657661的博客 315

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

java多线程 —— ThreadLocal

目录 1、什么是ThreadLocal? 2、为什么要用ThreadLocal? 3、ThreadLocal的内部实现? 4、怎么用ThreadLocal? 1、什么是ThreadLocal? ThreadLocal是一种变量类型,称为“局部变量类型”。一般用private static修饰。 2、为什么要用ThreadLocal? 提供线程间的数据隔离效果。 我们知道多线...

向来缘浅,奈何情深 1721

Java多线程中ThreadLocal解析

       Java多线程中,常常会用到这样一个类,ThreadLocal。这个类是用来干什么的呢,我们先来看一段代码。private static final ThreadLocal threadSession = new ThreadLocal(); public static Session getSession() throws InfrastructureException { ...

此心光明,亦复何言~ 364

ThreadLocal类解决多线程同步问题

问题引出 我们简单写一段代码,创建三个线程获取信息,代码如下 package dataStructure; public class ThreadLocalDemo { public static void main(String[] args) { new Thread(()->{Message msg = new Message() ; msg.setInfo("第一个线程"); Channel.setMessage(msg); Channel.send();} , "线程A"

sapere_aude的博客 1188

多线程 ThreadLocal

1、JDK解释:ThreadLocal的作用是提供线程内的局部变量,这种变量在多线程环境下访问时能够保证各个线程里变量的独立性。 ThreadLocal不是一个线程,而是一个线程的本地化对象。当某个变量在使用ThreadLocal进行维护时,ThreadLocal为使用该变量的每个线程分配了一个独立的变量副本,每个线程可以自行操作自己对应的变量副本,而不会影响其他线程的变量副本。 2、...

cf的博客 225

多线程中ThreadLocal踩坑

前言 记录一下在测试过程中,遇到的一个有关ThreadLocal的问题,顺便学习一下ThreadLocal相关的知识。 ThreadLocal介绍 ThreadLocal是一个关于创建线程局部变量的类。 要点: * 在当前线程中,任何一个地方都可以访问到ThreadLocal的值。 * 当前线程保存在ThreadLocal中的值只能被当前线程访问,一般情况下其他线程访问不到。 ...

沐上云霄的博客 4968

Java 多线程之 ThreadLocal 的使用

ThreadLocal 用于在多线程环境中维护线程封闭(thread-local)的变量。线程封闭是一种确保变量在多线程环境中的线程安全性的机制,每个线程都有自己独立的变量副本,互不干扰。ThreadLocal 提供了一种简单的方式来实现线程封闭,它为每个线程都创建了一个独立的变量副本。使用场景保存线程私有数据:当多个线程需要访问某个数据,但每个线程都需要有自己的数据副本时,可以使用 ThreadLocal。

QIFU的专栏 1668

Java多线程之ThreadLocal的特点

ThreadLocal用于提供线程的局部变量,在多线程环境里,每个线程的局部变量独立于其他线程的局部变量。也就是说 ThreadLocal 可以为每个线程创建一个【单独的变量副本】,相当于线程的 private static 类型变量。 ThreadLocal 的作用和同步机制有些相反:同步机制是为了保证多线程环境下数据的一致性;而 ThreadLocal 是保证了多线程环境下数据的独立性。 ...

L_R 625

ThreadLocal 和多线程有什么区别

ThreadLocal与多线程的区别与配合使用 ThreadLocal是为解决多线程共享变量冲突而设计的线程隔离机制,每个线程拥有独立的变量副本,常用于保存用户信息、事务连接等线程私有数据。而多线程技术(Thread/Executor)主要用于实现任务并发执行,提升程序吞吐量。两者的核心区别在于:ThreadLocal不控制线程运行但保证线程安全,多线程则管理线程生命周期但需额外处理线程安全问题。

chenxuefeng_accp的专栏 801

java threadlocal 缺点_Java 多线程 — ThreadLocal 的应用及原理

原标题:Java 多线程 — ThreadLocal 的应用及原理在涉及到多线程需要共享变量的时候,一般有两种方法:其一就是使用互斥锁,使得在每个时刻只能有一个线程访问该变量,好处就是便于编码(直接使用synchronized关键字进行同步访问),缺点在于这增加了线程间的竞争,降低了效率;其二就是使用本文要讲的ThreadLocal。如果说synchronized是以“时间换空间”,那么Threa...

weixin_27734811的博客 347
上一篇: ELK第八篇:ElasticSearch: Index 和 Type 的区别
下一篇: 类加载机制:双亲委任模型和tomcat类加载器
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值