【弄nèng - 化繁为简】ThreadLocal原理与使用

本文详细解析ThreadLocal的作用,作为线程级别的局部变量,阐述其内部ThreadLocalMap结构,通过示例演示ThreadLocal如何避免线程间变量污染,并对比ThreadLocal与Map在并发环境中的行为差异。

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

文章目录

一. ThreadLocal

面试官经常问:“说说你对ThreadLocal的理解吧”
我们背诵的答案:

线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每个线程创建一个单独的变量副本,每个线程都可以改变自己的变量副本而不影响其它线程所对应的副本

说白了就是线程级别的局部变量,内部是ThreadLocalMap结构,每个线程内部都存在一个局部变量ThreadLocal.ThreadLocalMap threadLocals = null;,ThreadLocal的get,set实际操作的都是线程的局部变量threadLocals 。

Thread变量定义

class Thread implements Runnable {
  
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

ThreadLocal的API

方法名说明
get()返回此线程局部变量的当前线程副本中的值
set(T value)将线程局部变量当前副本中的值设置为指定值
remove()移除此线程局部变量当前副本中的值

get,set源码

	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 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();
    }

	ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

可以发现,每个线程中都有一个变量ThreadLocal.ThreadLocalMap,当执行get,set方法时都在操作当前线程的threadLocals变量,所以多个线程互不干扰。

示例

代码

public class ThreadLocalDemo {

    public static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static final Map userMap = new HashMap<>();

    public static void main(String[] args) throws InterruptedException {

        for (int i=0;i<2;i++) {
            // 睡一会
            Thread.sleep(3000);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("userThreadLocal:" + Thread.currentThread().getName() + ":" + userThreadLocal.get());
                    userThreadLocal.set(Math.random() * 100);
                    System.out.println("userThreadLocal:" + Thread.currentThread().getName() + ":" + userThreadLocal.get());

                    System.out.println("----------------");

                    System.out.println("userMap:" + Thread.currentThread().getName() + ":" + userMap.get("a"));
                    userMap.put("a", Math.random() * 100);
                    System.out.println("userMap:" + Thread.currentThread().getName() + ":" + userMap.get("a"));

                    System.out.println("====================================================");
                }
            }).start();
        }

    }
}

输出
在这里插入图片描述
分别定义了ThreadLocal 和Map变量,观察两个线程执行的区别,Map变量在第二个线程中获取到了第一个线程的值,而ThreadLocal 变量没有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值