ThreadLocal.ThreadLocalMap.Entry 这个类设计为 WeakReference 的子类是否有意义

以上是 ThreadLocal 的原理图,Thread对象内部会持有一个 ThreadLocal.ThreadLocalMap的对象threadLocals,ThreadLocalMap 是一个hash表可以存放多个键值对,key是ThreadLocal对象,value可以是任何对象,当 ThreadLocal 对象调用set 方法的时候,就会把ThreadLocal 对象自己作为key,要 set 的对象作为value,存入当前线程的threadLocals 这个 hash 表中,当然如果有多个ThreadLocal 对象调用 set 方法,那么当前线程的threadLocals中会有多个键值对。当ThreadLocal 对象调用 get 方法的时候,就会以ThreadLocal 对象自己作为key,从当前线程的threadLocals 这个 hash 表中获取一个value返回。

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

ThreadLocal 是 Java 中的一个类,它提供了线程局部(thread-local)变量的功能。这些变量与普通变量不同,因为每个访问这些变量的线程(通过其 get 或 set 方法)都会有该变量的一个独立初始化的副本。这意味着每个线程都可以独立地修改其副本,而不会影响到其他线程中的副本。

ThreadLocal 实例通常作为希望与线程关联状态的类的私有静态字段使用。例如,在 Web 应用程序中,你可能会使用 ThreadLocal 来存储用户 ID 或事务 ID,这样每个处理用户请求的线程都可以独立地访问和修改其关联的用户或事务信息,而不会与其他线程发生冲突。

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

每个线程都对其ThreadLocal变量的一个副本持有隐式引用(

这里其实是通过Thread.threadLocals这个属性对 ThreadLocal 对象进行引用,threadLocals的类型为ThreadLocal.ThreadLocalMap ,之所以叫做隐式引用是因为ThreadLocal.ThreadLocalMap.Entry继承了WeakReference,如果引用的ThreadLocal对象没有其他强引用的时候,可能会被垃圾回收器回收掉

),只要线程是活动的并且ThreadLocal实例是可访问的;当一个线程结束时,其所有ThreadLocal变量副本都将成为垃圾收集的目标(除非这些副本还存在其他引用)。

以上是ThreadLocal类中对该类的一个大概描述


public class ThreadLocal<T> {
    
    //这里将变量定义为 private final int,意味着该变量只有在创建新的ThreadLocal实例的
    //时候才会被赋值 同一个虚拟机内,不同的 ThreadLocal 实例的 threadLocalHashCode 是不同的
    private final int threadLocalHashCode = nextHashCode();

    /**
     * The next hash code to be given out. Updated atomically. Starts at
     * zero.
     * 创建一个新实例的时候需要用到该 hash code,赋值给 新实例的threadLocalHashCode,同时进行
     * 原子更新。该码从 0 开始
     */
    private static AtomicInteger nextHashCode =
        new AtomicInteger();

    /**
     * The difference between successively generated hash codes - turns
     * implicit sequential thread-local IDs into near-optimally spread
     * multiplicative hash values for power-of-two-sized tables.
     * 每次更新 nextHashCode 的时候,增加的量
     */
    private static final int HASH_INCREMENT = 0x61c88647;

    /**
     * Returns the next hash code.
     * 返回当前nextHashCode的值,并且将nextHashCode增加HASH_INCREMENT
     */
    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }



    /**
     * Creates a thread local variable.
     * @see #withInitial(java.util.function.Supplier)
     */
    public ThreadLocal() {
    }

    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        //先获取当前线程的 threadLocals 字段的值,threadLocals是一个实现了Map数据结构的        
        //ThreadLocalMap对象可以存放多个键值对,也就是我们在同一个线程中调用多个ThreadLocal对                
        //象的set方法的时候threadLocals 中就会有多个键值对
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            //获取当前线程的ThreadLocalMap对象中有没有以当前调用get方法的ThreadLocal对象作        
            //为key的键值对,如果有就返回该键值对的value字段的值
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }

        //如果当前线程还没有调用过任何一个ThreadLocal实例的set方法,那么当前线程的 
        //ThreadLocalMap 对象就为 null
        //这时候就得为当前线程初始化一个ThreadLocalMap,并设放入以initialValue方法的返回值作 
        //为value,以当前的ThreadLocal对象为key的键值对
        return setInitialValue();
    }

    /**
     * Variant o
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值