java 独立存储线程变量技术——ThreadLocal

本文详细介绍了ThreadLocal类在Java多线程编程中的应用。通过对比synchronized关键字,阐述了ThreadLocal如何为每个线程提供独立的变量副本,确保线程安全。同时给出了在Spring MVC框架中使用ThreadLocal封装request和response的具体实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在多线程编程中,我们使用(synchronized,ReentrantLock等)来确保多个线程共享的变量能被安全的访问。但是还有一些变量,我们希望每一个线程都能保存一份独立的值而不受其他线程的影响。这个时候我们就需要用到ThreadLocal这个类来完成相关操作。

ThreadLocal的作用


现有两个线程A和B,它们都能访问到一个变量str_c。在不经过任何处理时,str_c的值可以被A和B两个线程访问和修改。使用了ThreadLocal后将str_c作为一个线程的局部变量,对于每一个线程,通过ThreadLocal方法得到的str_c的值是该线程的str_c的值,这个值不会被其他线程修改,其他线程只能修改他们自己的str_c的值。在并发的代码中的任何一点我们都能访问ThreadLocal而获取str_c的值,但是获取的值是该线程的值,其他线程的str_c在这个时候被“屏蔽”了,一般情况下我们看不见且访问不到。

在工作项目中举例。在Java ee的springMVC框架中,我们在封装Controller时习惯于将request、response两个对象通过ThreadLocal封装,因为这两个对象在每个线程中的内容肯定不同,通过这种技术,可以确保在高并发情况下的安全性。

ThreadLocal与Synchronized比较


网上的部分博客对ThreadLocal与Synchronized的概念混淆不清。ThreadLocal的作用并不是取代Synchronized,这两种方法从初衷上就完全不同。不仅仅是初衷,这两种技术的实现方法也不同,不存在可比性。

ThreadLocal: 将每个线程持有的变量安全的存放起来,不被其他线程访问。
synchronized: 让多个线程并发访问的变量能够安全的被访问和操作。

ThreadLocal使用方法


ThreadLocal类本身并不是线程,这个类是用来创建并存放线程局部变量的。

方法含义
initialValue返回此线程局部变量的当前线程的“初始值”。线程第一次调用get方法前会调用此方法。
get返回此线程局部变量的当前线程副本中的值。
set将此线程局部变量的当前线程副本中的值设置为指定值。
remove移除此线程局部变量当前线程的值。

ThreadLocal 提供了线程局部变量并且通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。 例如,以下类通过重写initialValue方法生成对每个线程唯一的局部标识符。线程 ID 是在第一次调用 UniqueThreadIdGenerator.getCurrentThreadId() 时分配的,在后续调用中不会更改。

import java.util.concurrent.atomic.AtomicInteger;

 public class UniqueThreadIdGenerator {

     private static final AtomicInteger uniqueId = new AtomicInteger(0);

     private static final ThreadLocal < Integer > uniqueNum = 
         new ThreadLocal < Integer > () {
             @Override protected Integer initialValue() {
                 return uniqueId.getAndIncrement();
         }
     };

     public static int getCurrentThreadId() {
         return uniqueNum.get();
     }
 } 

ThreadLocal实现原理


ThreadLocal的实现方法有些复杂,愚以为这个技术可以不采用Map的方式来存放,其他的键值对存放方式也未尝不可,但是jdk采用的方法肯定有他正确的道理。ThreadLocal存放局部变量的底层实现主要涉及到三个类:ThreadLocal、ThreadLocalMap、Thread

ThreadLocal:
在这个类中,每当调用set方法传入值时先获得当前线程Thread对象,在Thread对象的私有变量中查看ThreadLocal.ThreadLocalMap类对象是否为空,如果不为空,将值和threadLocal的this对象传入ThreadLocalMap类中。

ThreadLocalMap:
ThreadLocalMap是TheadLocal的静态内部类,这也能够解释为什么在Thread类中ThreadLocalMap可以通过ThreadLocal.ThreadLocalMap(外部类.内部类)的方式声明。此类是一个简单实现的Map映射表和java集合框架中的Map类无关系。当有值传入时将线程对象和值以键值对的形式存放。

Thread:
这个类是当前线程类,其中包含ThreadLocal.ThreadLocalMap类型的私有变量,用该变量来存放本线程的局部变量,从而达到其他线程不能访问的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值