ThreadLocal的正确用法

ThreadLocal详解:线程私有变量的正确使用姿势 张三往自己口袋里放钱,不会影响李四的口袋李四从自己口袋里拿钱,也不会拿到张三的钱ThreadLocal就像给每个线程发了一个专属保险箱,让多线程编程变得简单安全。 阅读详情

目录(?)[+]

 

用法一:在关联数据类中创建private static ThreadLocal

ThreaLocal的JDK文档中说明:ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread。如果我们希望通过某个类将状态(例如用户ID、事务ID)与线程关联起来,那么通常在这个类中定义private static类型的ThreadLocal 实例。

例如,在下面的类中,私有静态 ThreadLocal 实例(serialNum)为调用该类的静态 SerialNum.get() 方法的每个线程维护了一个“序列号”,该方法将返回当前线程的序列号。(线程的序列号是在第一次调用SerialNum.get() 时分配的,并在后续调用中不会更改。)

  1. public class SerialNum {  
  2.     // The next serial number to be assigned  
  3.     private static int nextSerialNum = 0;  
  4.   
  5.     private static ThreadLocal serialNum = new ThreadLocal() {  
  6.         protected synchronized Object initialValue() {  
  7.             return new Integer(nextSerialNum++);  
  8.         }  
  9.     };  
  10.   
  11.     public static int get() {  
  12.         return ((Integer) (serialNum.get())).intValue();  
  13.     }  
  14. }  



【例】

 
public class ThreadContext {
 
  private String userId;
  private Long transactionId;
 
  private static ThreadLocal threadLocal = new ThreadLocal(){
    @Override
         protected ThreadContext initialValue() {
             return new ThreadContext();
        }
 
  };
  publicstatic ThreadContextget() {
    return threadLocal.get();
  }

  public String getUserId() {
    return userId;
  }
  public void setUserId(String userId) {
    this.userId = userId;
  }
  public Long getTransactionId() {
    return transactionId;
  }
  public void setTransactionId(Long transactionId) {
    this.transactionId = transactionId;
  }
 
}

 

用法二:在Util类中创建ThreadLocal

这是上面用法的扩展,即把ThreadLocal的创建放到工具类中。

【例】例如Hibernate的工具类:

public class HibernateUtil {
     private static Log log = LogFactory.getLog(HibernateUtil. class);
     private static final SessionFactory sessionFactory;      //定义SessionFactory
 
     static {
         try {
             // 通过默认配置文件hibernate.cfg.xml创建SessionFactory
            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            log.error( "初始化SessionFactory失败!", ex);
             throw new ExceptionInInitializerError(ex);
        }
    }

     //创建线程局部变量session,用来保存Hibernate的Session
     publicstatic final ThreadLocal session = new ThreadLocal();
 
     /**
     * 获取当前线程中的Session
     * @return Session
     * @throws HibernateException
     */

     public static Session currentSession() throws HibernateException {
        Session s = (Session) session.get();
         // 如果Session还没有打开,则新开一个Session
         if (s == null) {
            s = sessionFactory.openSession();
            session.set(s);          //将新开的Session保存到线程局部变量中
        }
         return s;
    }
 
     public static void closeSession() throws HibernateException {
         //获取线程局部变量,并强制转换为Session类型
        Session s = (Session) session.get();
        session.set(null);
         if (s != null)
            s.close();
    }
}

 
 

用法三:在Runnable中创建ThreadLocal

 还有一种用法是在线程类内部创建ThreadLocal,基本步骤如下:

1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。
2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。
3、在ThreadDemo类的run()方法中,通过调用getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。  
 
public class ThreadLocalTest implements Runnable{
    
     ThreadLocal<Studen> studenThreadLocal = new ThreadLocal <Studen >();

    @Override
     public void run() {
        String currentThreadName = Thread.currentThread().getName();
        System.out.println(currentThreadName + " is running...");
        Random random = new Random();
         int age = random.nextInt( 100);
        System.out.println(currentThreadName + " is set age: "   + age);
        Studen studen = getStudent(); //通过这个方法,为每个线程都独立的new一个student对象,每个线程的的student对象都可以设置不同的值
        studen.setAge(age);
        System.out.println(currentThreadName + " is first get age: " + studen.getAge());
         try {
            Thread.sleep( 500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println( currentThreadName + " is second get age: " + studen.getAge());
        
    }
    
     private Studen getStudent() {
        Studen studen = studenThreadLocal.get();
         if (null == studen) {
            studen = new Studen();
            studenThreadLocal.set(studen);
        }
         return studen;
    }

     public static void main(String[] args) {
        ThreadLocalTest t = new ThreadLocalTest();
        Thread t1 = new Thread(t, "Thread A");
        Thread t2 = new Thread(t, "Thread B");
        t1.start();
        t2.start();
    }
    
}

class Studen{
     int age;
     public int getAge() {
         return age;
    }
     public void setAge( int age) {
         this.age = age;
    }
    
}
 
 
C++11的thread_local原理和应用范例 C++11引入了thread_local来保证线程访问全局数据的安全,thread_local告诉线程进行数据本地存储(线程本地存储一个数据备份),从而消除线程间数据竞争的一种方式。 阅读详情

相关推荐

多线程 - ThreadLocal怎么使用

ThreadLocal是Java中一个线程本地变量工具类,它可以使变量只被同一个线程访问和修改,从而避免了线程安全问题。ThreadLocal通常用于在多线程环境下存储和获取线程本地的数据,比如用户身份认证信息、数据库连接、Session对象等。需要注意的是,在使用ThreadLocal时,应该避免过度依赖它来实现数据传递,因为这样可能会导致代码可读性和可维护性降低。需要注意的是,每个线程都需要使用自己的ThreadLocal对象,否则会出现线程安全问题。

学无止境 539

史上最全最详细的ThreadLocal 使用

文章目录ThreadLocal 简介ThreadLocal 的四个方法 ThreadLocal 简介 一种解决多线程环境下成员变量的问题的方案,但是与线程同步无关,其思路是为每一个线程创建一个单独的变量副本,从而每个线程都可以独立地改变所拥有的变量副本,而不会影响其他线程所对应的副本。 ThreadLocal不是用于解决共享变量的问题的,也不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制。 ThreadLocal 的四个方法 void set(Object value)

半夏_2021的博客 1万+

Cadence Design Entry HDL 使用教程

Cadence Design Entry HDL 使用教程 前言 cadence Design Entry HDL是cadence内部集成的一款板级的EDA设计工具,早期叫 concept HDL。其为cadence最早的原配板级电路图绘制工具,只不过由于后来cadence收购了orcad然后就将旗下的capture CIS收入其中,由于后者使用起来上手简单,所以后者更为大家所熟知。虽然大家对...

uio159753的博客 4万+

浅谈ThreadLocal

1. ThreadLocal简介 ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。 ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thr

大家好,我是千楼,全栈开发工程师,分享日常学习和工作,记录成长~~~ 5296

VC Spyglass CDC实战:从TCL脚本到SDC约束的完整避坑指南

本文是一份针对数字IC验证工程师的VC Spyglass CDC实战指南。文章详细阐述了从TCL脚本环境搭建、SDC约束编写到典型CDC违规(如SETUP_PORT_UNCONSTRAINED)诊断与修复的完整流程,旨在帮助读者高效避坑,深入理解工具逻辑,从而完成可靠的时钟域交叉验证。

go5gopher的博客 382

我用两种方式玩转 MCP:CherryStudio vs VS Code 实测手记

MCP,全称,你可以理解为——给大模型装上“手脚”和“工具箱”。传统大模型像一位博学但手不能动的学者:“我知道怎么算圆周率,但没法打开计算器。而支持 MCP 的模型,能通过标准协议自动调用外部工具(比如fetch网络请求、readFile读文件、shell执行命令),真正做到“知行合一”。输入后**,保存,**之后就显示出来了MCP 不是“魔法”,而是把 AI 从“问答机”升级为“智能代理”的关键一步。工具本身不难,难的是“知道它能解决什么问题”。

zyq569的博客 1020

ThreadLocal的正确用法 .

用法一:在关联数据类中创建privatestaticThreadLocalThreaLocal的JDK文档中说明:ThreadLocalinstancesaretypicallyprivatestaticfieldsinclassesthatwishtoassociatestatewithathread。如果我们希望通过某个类将状态(例如用...

weixin_33787529的博客 155

educoder数字逻辑实训:寄存器设计与应用(Logisim)

第1关:基本寄存器的设计 任务描述 本关任务:在Logisim中,构建由4个D触发器构成的4位基本寄存器,要求上升沿触发,具有异步复位功能。 第2关:移位寄存器的设计 任务描述 本关任务:在Logisim中,构建由4个D触发器构成的4位右移移位寄存器,要求上升沿触发,具有异步复位功能。 第3关:循环移位寄存器的设计 任务描述 本关任务:在Logisim中,构建由4个D触发器构成的4位循环右移移位寄存器,要求上升沿触发,具有异步复位功能以及并行数据同步加载功能。 第4关:并行..

qq_52209002的博客 1万+

java中local使用,java 中ThreadLocal 的正确用法

用法一:在关联数据类中创建private static ThreadLocalThreaLocal的JDK文档中说明:ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread。如果我们希望通过某个类将状态(例如用户ID、事务ID)与线...

weixin_42131352的博客 449

eNSP网络构建—建立小型局域网

企业私有网络构建运维 实战案例——使用模拟器构建局域网络 案例分析 1.架构分析 (1)需求分析 本实验的目的在于建立小型局域网。由于公司由不同部门组成,并分布在不同地点,因此需要划分不同网络实现互联互通。设计以下网络:两个部门各使用一台交换机连接,然后连接到总交换机,再通过路由器与外网以及其他部门网络相连。为了控制网络上的广播风暴,增加网络的安全性,在交换机上需要设置VLAN,在路由器与交换机之...

_ 4万+

DeepSeek R1-32B医疗大模型的完整微调实战分析(全码版)

【代码】DeepSeek R1-32B医疗大模型的完整微调实战指南(全码版)

AllenLV的博客 5101

java threadLocal 测试

package thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadLocalTest { public ThreadLocalTest() { } public static voi

xiaomin1991222的专栏 277

Field Characteristics 深入解析,理解 SAP ABAP Analytics 中 Dimension 与 Measure 的真正边界

在SAP ABAP Analytics数据模型中,字段应建模为Dimension还是Measure,关键在于业务语义而非数据类型。Dimension提供分析上下文,构成数据坐标系,支持钻取与切片;Measure则需具备明确聚合语义(如#SUM、#MIN、#MAX),且必须满足Distinct(无重复)与Complete(无缺失)原则,确保聚合结果准确。错误的建模会导致聚合偏差,根源常在事实粒度不清或关联关系不当。因此,正确划分字段角色,本质是让Analytical Engine准确理解业务数据的分析逻辑。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 56

python ThreadLocal

是threading模块中的一个类,用于创建线程局部变量。为每个线程创建独立的“全局变量”副本,每个线程对该变量的读写互不影响。适合多线程环境下,每个线程都需要有自己独立的数据副本的场景(如数据库连接、用户会话等)。用于创建线程局部变量,每个线程有自己的“全局变量”副本,互不干扰。普通变量(全局/局部)无法实现线程间自动隔离。,然后,在不同线程中赋值和访问。

qq_37805832的博客 411

【49】软考软件设计师——冲刺复盘:高频易错点与应试策略|复盘清单+应试技巧

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏第49篇,属于**模块六:冲刺与模拟**终篇,聚焦考前最后阶段的“精准复盘+应试提分”。全文围绕“高频易错点清零、答题时间优化、应急处理落地”三大核心,梳理9大知识领域的典型易错点(附避坑技巧)、优化版答题时间分配(含取舍策略)、考中全场景应急方案,配套可直接使用的“复盘清单”和“应试技巧手册”,帮助考生在最后阶段查漏补缺、固化得分逻辑,避免因低级错误丢分,以“稳、准、快”的状态应对考试。下一篇第50篇(终章)将进行全专栏知识体系回顾、考试策略总结

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 439

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

ThreadLocal弱引用,既然 GC时立即回收,为什么还需要手动remove

措施解决的问题必要性弱引用Key防止ThreadLocal对象内存泄漏✅ 必要手动remove防止Value对象内存泄漏✅ 必要使用try-finally确保remove一定执行✅ 强烈推荐弱引用只是防御了一半的内存泄漏风险,手动remove才是完整的解决方案。特别是在线程池等长期存活的线程场景中,必须严格遵循"谁set谁remove"的原则。

C18298182575的博客 998

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

如何正确使用ThreadLocal

ThreadLocal是jdk版本引入的类:java.lang.ThreadLocal,使得每个线程可以独享变量副本,起到线程安全的作用。线程局部性的,ThreadLocal变量能在所属线程执行的各个方法中共享但是不需要在执行方法链中显示传递参数,也就是线程局部的执行方法链的全局变量。首先说下,ThreadLocal、Thread、ThreadLocalMap、ThreadLocalMap.Entry、WeakReference这几个类之间的关系,这关系着ThreadLocal在jdk源代码层面的实现。 同

titi223的博客 1120

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

efm32 入门.pdf

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

threadlocal用法_一文带你彻底搞懂ThreadLocal

前言共享变量一直是并发中的老大难问题,每个线程都对它有操作权,所以线程之间的同步很关键,锁也就应运而生。这里换一个思路,是否可以把共享变量私有化?即每个线程都拥有一份共享变量的本地副本,每个线程对应一个副本,同时对共享变量的操作也改为对属于自己的副本的操作,这样每个线程处理自己的本地变量,形成数据隔离。事实上这就是ThreadLocal了。就线程同步而言,锁可以认为是时间换空间,ThreadLoc...

weixin_39864571的博客 259

ThreadLocal

ThreadLocal 为每一个线程赋值一份变量副本(创建一个ThreadLocal对象,用来为每个线程保存一份变量,实现线程封闭) 底层使用一个ThreadLocalMap对象存储 使用ThreadLocal存在内存泄露问题: ​ 使用ThreadLocal对象作为键,是弱引用,可以被回收掉,键为null,但是value值为强引用,不会被回收掉 ThreadLocal正确的使用方法: ​ 建议:每次使用完ThreadLocal都调用它的remove()方法清除数据. 线程池 ​ 任务多且简单时,为了减少频

m0_51683428的博客 168
上一篇: Java线程:深入ThreadLocal
下一篇: java中ThreadLocal类的使用
ichsonx
博客等级 码龄19年 202粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值