ThreadLocal 详解

总体介绍:
ThreadLocal 是 Java 中的一个类,用于提供线程局部变量,即每个线程都有自己独立的变量副本。即使在一个类中定义了静态的 ThreadLocal 对象,每个线程在访问这个 ThreadLocal 对象时,实际上访问的是各自线程内部的独立副本,而不是共享的实例。

ThreadLocal 的工作原理是这样的:

  1. 当一个线程首次访问 ThreadLocal 对象的 get() 或 set() 方法时,ThreadLocal
    会为该线程创建一个独立的变量副本。
  2. 这个副本存储在每个线程自己的 ThreadLocalMap 中,ThreadLocalMap 是 Thread 类的一个成员变量。
  3. ThreadLocalMap 是一个特殊的哈希表,它的键是 ThreadLocal 对象本身值是线程局部变量的副本
  4. 当线程调用 ThreadLocal 的 get() 方法时,ThreadLocal 会查找该线程的
    ThreadLocalMap,并返回与当前 ThreadLocal 对象关联的值。
  5. 当线程调用 ThreadLocal 的 set() 方法时,ThreadLocal 会更新该线程的 ThreadLocalMap 中与当前 ThreadLocal 对象关联的值。
  6. 相关源码如下:
    /* ThreadLocalMap 是 Thread 类的一个成员变量。
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

/** set方法源码 
	Sets the current thread's copy of this thread-local variable to the specified value. Most subclasses will have no need to override this method, relying solely on the initialValue method to set the values of thread-locals.
	Params:
	value – the value to be stored in the current thread's copy of this thread-local.*/ 
  public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t); // 后续获取都是当前线程自身的 threadLocals 对象
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value); // 通过它进行初始化
            
/** get 方法源码
	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 initialValue method.
	Returns: the current thread's value of this thread-local */
  public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t); // 后续获取都是线程自身的 ThreadLocalMap 
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue(); // 设置一个默认值 null

    /** 初始化线程本地的ThreadLocalMap 源码
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    
    /** 获得当前线程对象的自己独有的 ThreadLocalMap 对象
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    
     /** ThreadLocalMap 构造方法源码(map结构得出每个ThreadLocal对象只能对应一个值)
       * Construct a new map initially containing (firstKey, firstValue).
       * ThreadLocalMaps are constructed lazily, so we only create
       * one when we have at least one entry to put in it.
       */
      ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
          table = new Entry[INITIAL_CAPACITY]; // 初始容量-必须是2的幂。默认 16
          int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
          table[i] = new Entry(firstKey, firstValue);
          size = 1;
          setThreshold(INITIAL_CAPACITY);
      }

总结:
ThreadLocal 的设计目的是为每个线程提供一个独立的变量副本,以便每个线程可以独立地修改自己的副本而不影响其他线程。因此,ThreadLocal 的 set() 方法只会更新当前线程的 ThreadLocalMap 中对应的值,而不是添加多个值。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值