两种场景,殊途同归

  • ThreadLocalMap类,也就是Thread.threadLocals
  • ThreadLocalMap类是每个线程Thread类里面的变量,里面最重要的是一个键值对数组Entry[] table,可以认为是一个Map,键值对:
    • 键:这个ThreadLocal
    • 值:实际需要的成员变量,比如User或者SimpleDateFormat

ThreadLocalMap虽然类似HashMap但是处理处理Hash冲突略有不同

ThreadLocalMap采用的是线性探测法,也就是如果发生Hash冲突,就继续寻找下一个空位,而不是采用链表拉链

ThreadLocal两种使用场景殊途同归

  • 通过源码分析可以看出,setInitialValue和直接set最后都是利用map.set()方法来设置值
  • 也就是说,最后都会对应到ThreadLocalMap的一个Entry,只是起点和入口不一样

Thread类:

public class Thread implements Runnable{
    /**声明ThreadLocalMap类对象,它可以存储多个ThreadLocal静态常量的哈希标记
     * 而一个ThreadLocal静态常量可以维护一个线程内变量
     * 即一个ThreadLocalMap类对象可以存储多个线程内变量,而这些变量的key就是它们各自的维护者:ThreadLocal静态常量的哈希标记
     * **/
    ThreadLocal.ThreadLocalMap threadLocals =null;
    /**返回对当前执行的线程对象的引用,“native”表示该方法是由c语言编写的底层方法*/
    public static native Thread currentThread();
    @Override
    public void run() {
        //省略
    }
}

ThreadLocal类:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**原理,类似于访问者模式,ThreadLocal是访问者,Thread是被访问者。
 * ThreadLocal访问的是Thread的局部变量ThreadLocalMap
 * 当使用ThreadLocal维护变量时,ThreadLocal为每个【使用该变量的线程】提供独立的变量副本,
 * 所以每个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本.
**/
public class ThreadLocal<T> {
    //线程的内部变量ThreadLocalMap对象    对ThreadLocal对象所维护的  线程内变量   的一种哈希标记
    private final int threadLocalHashCode = new AtomicInteger().getAndAdd(0x61c88647);
    //定义ThreadLocalMap内部类
    static class ThreadLocalMap{
        //源码逻辑是一种哈希映射,这里暂时用Map替代
        //以当前ThreadLocal对象的标记 作为key
        Map<Integer,Object> m = new HashMap<Integer,Object>();
        public ThreadLocalMap(ThreadLocal threadLocal, Object firstObj) {
            //--省略
        }
        void set(ThreadLocal threadLocal, Object value){
            m.put(threadLocal.threadLocalHashCode, value);
        }
        Object get(ThreadLocal threadLocal){
            return m.get(threadLocal.threadLocalHashCode);
        }
        void remove(){}
    }
    //访问的是Thread的局部变量ThreadLocalMap,并为其注入值
    public void set(T t){
          //获取当前线程,然后获取到当前线程里面的ThreadLocalMap引用
          ThreadLocalMap map = Thread.currentThread().threadLocals;
          //以当前ThreadLocal对象为参数
          map.set(this,t);
    }
    
    //访问的是Thread的局部变量ThreadLocalMap,并获取其值
    public T get(){
          ThreadLocalMap map = Thread.currentThread().threadLocals;
          if(null!=map){
              return  (T) map.get(this);
          }
          //如果为空,则初始化(创建并设置对象副本)
          return setInitialValue();
    }
    
    private T setInitialValue(){
         Thread thread = Thread.currentThread();
         ThreadLocalMap map = thread.threadLocals;
         if (map != null)
             map.set(this, null);
         else
             map = new ThreadLocalMap(this, null);
         return null;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值