美文网首页
ThreadLocal分析

ThreadLocal分析

作者: zxcvbnmzsedr | 来源:发表于2018-06-28 22:20 被阅读0次

    ThreadLocal介绍

    ThreadLocal类用来提供线程内部的局部变量。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。

    只要线程处于活动状态就能够访问到ThreadLocal实例,在一个线程消失之后,所有线程本地实例副本都会被垃圾收集器收集,除非存在对这些副本的其他引用。

    实现原理

    ThreadLocal可以看成是一个容器,只是存在的变量是当前线程的而已。

    [图片上传失败...(image-eeace1-1530195633300)]

    它提供了三个对外的方法分别是 set(T) 、get()、remove()

    ThreadLocalMap对象

    ThreadLocal是的实现都是基于ThreadLocalMap来处理的。

    ThreadLocalMap实现了一个定制化的Map数据结构的对象。

    [图片上传失败...(image-dd9d9-1530195633300)]

    ThreadLocalMap初始化

    创建的时候会初始化用于存储ThreadLocal对象的数组,
    初始化的数组长度为16,这个数组对象会被当前线程所共享。

    如果一个线程所持有的ThreadLocal对象超过16个会进行重新hash并进行扩容。

    private static final int INITIAL_CAPACITY = 16;
    
    private Entry[] table;
    
    ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
        table = new Entry[INITIAL_CAPACITY];
        int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
        table[i] = new Entry(firstKey, firstValue);
        size = 1;
        setThreshold(INITIAL_CAPACITY);
    }
    private void setThreshold(int len) {
        threshold = len * 2 / 3;
    }
    

    Entry

    Entry是一个弱引用对象,使用ThreadLocal作为建。

    如果一个ThreadLocal没有被其他任何强引用指向时,如果GC运行这个对象就会被回收。

    这样能够保证,如果使用ThreadLocal的线程被销毁时,ThreadLocal也会被回收。

    
       static class Entry extends WeakReference<ThreadLocal<?>> {
           Object value;
           Entry(ThreadLocal<?> k, Object v) {
               super(k);
               value = v;
           }
       }
        
    

    set方法

    
    public void set(T value) {
        // 获取当前所在的线程
        Thread t = Thread.currentThread();
        // 获取当前所在线程的ThreadLocalMap对象
        ThreadLocalMap map = getMap(t);
        // 如果存在直接塞值,如果不存在进行创建再塞值
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    

    get方法

    
    public T get() {
        // 获取当前所在的线程
        Thread t = Thread.currentThread();
        // 获取当前所在线程的ThreadLocalMap对象
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            // 如果获取到的变量不为空则直接返回
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        // 如果上面的代码没有走通,说明没有找到值,会塞一个空值进去
        return setInitialValue();
    }
    
    private T setInitialValue() {
        // initialValue这个返回的是一个null
        T value = initialValue();
        // 进行创建操作
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    

    remove方法

    public void remove() {
         // 获取当前线程对应的map对象,然后移除
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
    }
    

    相关文章

      网友评论

          本文标题:ThreadLocal分析

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