美文网首页
ThreadLocal的实现

ThreadLocal的实现

作者: Wi1ls努力努力再努力 | 来源:发表于2020-10-27 17:57 被阅读0次

    基于Android 7.0分析


    关键的几个点先列出来

    public class ThreadLocal<T> {
    
    
      public T get(){
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if(map != null){
          ThreadLocalMap.Entry e  = map.getEntry(this);
          if(e!=null)
            return (T)e.value;
        }
        return setInitialValue();
      }
    
      public void set(T value){
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if(map !=null ){
          map.set(this, value);
        }else{
          createMap(t, value);
        }
      }
    
      ThreadLocalMap getMap(Thread t){
        return t.threadLocals;
      }
    
      void createMap(Thread t, T firstValue){
        t.threadLocals = new ThreadLocalMap(this, firstValue);
      }
    }
    

    可以看到核心了,ThreadLocal链接了Thread和ThreadLocalMap

    public class Thread implements Runnable{
    
      ThreadLocal.ThreadLocalMap threadLocals = null;
    }
    

    所以,ThreadLocal保存的数据是存在线程自身的成员变量ThreadLocal.ThreadLocalMap中的

    //ThreadLocal.java
    static class ThreadLocalMap{
      static class Entry extends WeakReference<ThreadLocal>{
        Object value;
        Entry(ThreadLocal k, Object v){
          super(k);
          value = v;
        }
      }
    
      private Entry[] table;
      private Entry getEntry(ThreadLocal key){
        int i = key.threadLocalHashCode & (table.length -1);
        Entry e = table[I];
        if(e!=null && e.get() ==key){
          return e;
        }
      }
    
      private void set(ThreadLocal key, Object value){
        Entry[] tab = table;
        int len = tab.length;
        int i = key.threadLocalHashCode & (lend -1);
        
        for(Entry e = tab[I],e!=null;e=tab[I = nexIndex(I,len)]){
           ThreadLocal k = e.get();
            if(k==key){
              e.value = value;
              return;
            }
        }
        ....
        rehash();
      }
    }
    
    

    那我们是怎么使用的呢,我们会先实例化一个ThreadLocal对象,随后在线程调用set(T) or get() @ThreadLocal方法。
    从上面可以看出,每个线程都有一个ThreadLocal.ThreadLocalMap对象,其中又有一个数组Entry[],每次进行set/get的时候,会将这个ThreadLocal作为key,保存在线程的ThreadLocal.ThreadLocalMap中,保存的过程是通过将ThreadLocal进行hash取模保存在Entry[]中,如果发生了Hash冲突,就取下一个点位

    private static int nextIndex(int I, int len){
      return ((I+1 > len)? I+1:0);
    }
    

    为了防止内存泄漏,Entry还继承自WeakReference<ThreadLocal>

    相关文章

      网友评论

          本文标题:ThreadLocal的实现

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