ThreadLocal源码解析,以及ThreadLocal、ThreadLocalMap、Thread 三者之间的关系

本文详细解析了Java中的ThreadLocal、ThreadLocalMap与Thread三者之间的关系,包括它们的源码解析、实例代码以及ThreadLocal的安全性特点与InheritableThreadLocal的比较。

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

ThreadLocal、ThreadLocalMap、Thread 三者之间的关系

ThreadLocalMap 是 ThreadLocal 的内部类,Thread 中有个 ThreadLocalMap 成员变量 threadLocals 


ThreadLocal源码解析

下面看一下,jdk 关于 ThreadLocal api


ThreadLocal类 get 方法源码

public Object get()
    {
        Thread thread = Thread.currentThread();
        ThreadLocalMap threadlocalmap = getMap(thread);
        if(threadlocalmap != null)
        {
            ThreadLocalMap.Entry entry = threadlocalmap.getEntry(this);
            if(entry != null)
                return entry.value;
        }
        return setInitialValue();
    }

private Object setInitialValue()
    {
        Object obj = initialValue();
        Thread thread = Thread.currentThread();
        ThreadLocalMap threadlocalmap = getMap(thread);
        if(threadlocalmap != null)
            threadlocalmap.set(this, obj);
        else
            createMap(thread, obj);
        return obj;
    }

protected Object initialValue()
    {
        return null;
    }
当get一个值时,
获取当前线程,调用 getMap 方法获取当前线程的 ThreadLocalMap,如果获取的 ThreadLocalMap != null 那么就将 ThreadLocalMap 中保存的 value 返回给调用者。如果获取的 ThreadLocalMap == null 那么调用 setInitialValue 方法,setInitialValue方法中调用了 initialValue 方法,并将 initialValue 方法的返回值 obj 保存到 ThreadLocalMap 中,然后将 返回值 obj 返回给调用者。

ThreadLocal类 set 方法源码

public void set(Object obj)
    {
        Thread thread = Thread.currentThread();
        ThreadLocalMap threadlocalmap = getMap(thread);
        if(threadlocalmap != null)
            threadlocalmap.set(this, obj);
        else
            createMap(thread, obj);
    }

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

void createMap(Thread thread, Object obj)
    {
        thread.threadLocals = new ThreadLocalMap(this, obj);
    }

当set一个值时,获取当前线程,调用 getMap 方法获取当前线程的 ThreadLocalMap,如果获取的 ThreadLocalMap == null 那么调用 createMap 方法创建一个ThreadLocalMap,并将 obj 放入到 ThreadLocalMap 中。(注意:ThreadLocalMap 中 key 是 ThreadLocal,value 是 传入的 obj参数。 为什么ThreadLocalMap 中 key 是 ThreadLocal,因为一个线程可以有多个 ThreadLocal )

ThreadLocal类 remove 方法源码

public void remove()
    {
        ThreadLocalMap threadlocalmap = getMap(Thread.currentThread());
        if(threadlocalmap != null)
            threadlocalmap.remove(this);
    }

删除当前 ThrealLocal 对应的 value

实例代码

public static void main(String[] args) {
		ThreadLocal<String> tl = new ThreadLocal<String>();
		String str = tl.get();
		System.out.println("输出字符串:" + str);
	}
输出结果
输出字符串:null

public static void main(String[] args) {
	ThreadLocal<String> tl = new ThreadLocal<String>(){
		@Override
		protected String initialValue() {
			return "lp";
		}
	};
	String str = tl.get();
	System.out.println("输出字符串:" + str);
}

输出结果
输出字符串:lp

至于为什么输出结果 不一样,我想打架看了上面的源码解析应该都明白了吧。

如果不想重写 ThreadLocal 中的 initialValue 方法 也可以先调用 set 方法 再 调用 get 方法,就像下面这样

public static void main(String[] args) {
	ThreadLocal<String> tl = new ThreadLocal<String>();
	tl.set("lp");
	String str = tl.get();
	System.out.println("输出字符串:" + str);
}

输出结果
输出字符串:lp



补充

ThreadLocal 的线程安全性稍差的堂兄弟,InheritableThreadLocal

ThreadLocal 类有一个亲戚,InheritableThreadLocal,它以相似的方式工作,但适用于种类完全不同的应用程序。创建一个线程时如果保存了所有 InheritableThreadLocal 对象的值,那么这些值也将自动传递给子线程。如果一个子线程调用 InheritableThreadLocal 的 get() ,那么它将与它的父线程看到同一个对象。为保护线程安全性,您应该只对不可变对象(一旦创建,其状态就永远不会被改变的对象)使用InheritableThreadLocal ,因为对象被多个线程共享。 InheritableThreadLocal 很合适用于把数据从父线程传到子线程,例如用户标识(user id)或事务标识(transaction id),但不能是有状态对象,例如 JDBC Connection 。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值