美文网首页
ThreadLocal

ThreadLocal

作者: cqxxxxxxxx | 来源:发表于2021-05-27 16:49 被阅读0次
    注意点
    1. 线程本地变量

      即每个线程对象都维护了自己的ThreadLocalMap,只访问自己的Map,所以是安全的。

      Thread类里面有ThreadLocal.ThreadLocalMap属性,threadLocals和inheritableThreadLocals,以此保证每个线程都维护一份自己的数据

    2. 内存泄露

      ThreadLocalMap的Entry[] table中Entry继承了WeakReference,其中Key即ThreadLocal对象是弱引用,是为了避免内存泄露。 为什么能避免呢? 如下

      已知存在Thread->ThreadLocalMap->Entry->Key(ThreadLocal)的引用联关系。假设ThreadLocalMap.Entry中的ThreadLocal不设置成弱引用,那么当你在一个方法体内大量创建ThreadLocal并进行set操作之后,即使你该方法执行完了,创建的ThreadLocal对象引用也没有逃逸出该方法,但是它永远GC不掉,因为任然有开头说的Thread这边的强引用,所以这种无用对象一直堆积而得不到GC,就产生了内存泄露。

      不过一般我们都不会在方法体内创建ThreadLocal,一般是private static ThreadLocal创建的。所以也不会泄露问题。

      image

      引用链关系图

      1. ThreadLocalMap哈希冲突

        set方法时候处理hash冲突的方式是调用nextIndex(index, length)方法,其实就是在当前index基础上+1

    流程

    1. private static ThreadLocal<String> threadLocal = new ThreadLocal<>();

      new ThreadLocal<>()是空构造器,只不过会初始化实例变量,threadLocalHashCode

    2. threadLocal.set("nmm")

     public void set(T value) {
         //获取当前线程的ThreadLocalMap对象
         Thread t = Thread.currentThread();
         ThreadLocalMap map = getMap(t);
         //存在则用该ThreadLocal作为Key,设置进去
         if (map != null)
         map.set(this, value);
         else
         //不存在则创建map,同时设置value
         createMap(t, value);
         }
    
    3.  `threadLocal.get("nmm")`
    
    public T get() {
             //获取当前线程绑定的map
             Thread t = Thread.currentThread();
             ThreadLocalMap map = getMap(t);
             if (map != null) {
             //map中查找该ThreadLocal的entry,返回值
             ThreadLocalMap.Entry e = map.getEntry(this);
             if (e != null) {
             @SuppressWarnings("unchecked")
             T result = (T)e.value;
             return result;
             }
             }
             return setInitialValue();
             }
    
        4.  `threadLocal.remove()`主要就调用ThreadLocalMap.remove方法
    
    public void remove() {
                 ThreadLocalMap m = getMap(Thread.currentThread());
                 if (m != null)
                 m.remove(this);
                 }
    
                 private void remove(ThreadLocal<?> key) {
                 Entry[] tab = table;
                 int len = tab.length;
                 int i = key.threadLocalHashCode & (len-1);
                 for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                 if (e.get() == key) {
                 //把Reference的referent关联的ThreadLocal 清除
                 e.clear();
                 //清理map中key为null的value,跟weakHashMap一样
                 expungeStaleEntry(i);
                 return;
                 }
                 }
                 }
    

    相关文章

      网友评论

          本文标题:ThreadLocal

          本文链接:https://www.haomeiwen.com/subject/lkrdsltx.html