ThreadLocal源码分析

ThreadLocal源码分析

一、关键类分析

1.1ThreadLocal:

ThreadLocal内部有一个ThreadLocalMap静态内部类。

ThreadLocalMap内部类有静态内部类Entry和Entry数组,Entry内部就一个域value用于保存数据,构造方法参数为ThreadLocal和要设置的value。ThreadLocalMap是一个数组实现的map。它的key就是ThreadLocal。

 

1.2 Thread类分析

thread类里面维护了一个TheadLocal.ThreadLocalMap成员变量。

public class Thread implements Runnable {

   ThreadLocal.ThreadLocalMap threadLocals = null;

}

 

二、关键方法分析

2.1 get方法分析

        ①第一步拿到当前的线程,

②拿到当前的线程的ThreadLocalMap成员变量。若当前的ThreadLocalMap对象为空,那么进行初始化。

new ThreadLocalMap(this, firstValue);将当前ThreadLocal对象作为key构造ThreadLocalMap对象。

    ③将当前的ThreadLocal对象当做key去ThreadLocalMap中取值。

2.2 set方法分析

①第一步拿到当前的线程

②拿到当前的线程的ThreadLocalMap成员变量

③将值设置到key为当前threadlocal对象,value就是传入的参数的ThreadLocalMap中。若ThreadLocalMap对象不存在那么要进行初始化。

2.3 remove方法分析

①拿到当前的线程ThreadLocalMap成员变量

②将ThreadLocalMap数组中当前ThreadLocal对象对应下标索引处的对象设置为null

三、ThreadLocal内存泄露分析

   我们看源码发现ThreadLocalMap中的静态内部类Entry继承了WeakReference,即引用,也就是说他对ThreadLocal对象的引用是引用,当ThreadLocal对象没有外部强引用引用它,那么gc发生后ThreadLocal对象将会回收,那么ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,一直存在一条强引用链,hread Ref -> Thread -> ThreaLocalMap -> Entry -> value,永远无法回收,造成内存泄露。

public class ThreadLocal<T> {

  public T get() {

        ①第一步拿到当前的线程

        Thread t = Thread.currentThread();

②拿到当前的线程的ThreadLocalMap成员变量

        ThreadLocalMap map = getMap(t);

        if (map != null) {

//若threadlocalmap非空,那么根据当前的threadlocal对象找到值

            ThreadLocalMap.Entry e = map.getEntry(this);

            if (e != null) {

                T result = (T)e.value;

                return result;

            }

        }

//若threadlocalmap为空,那么进行初始化

        return setInitialValue();

}

//返回线程的ThreadLocalMap类型的成员变量threadLocals

ThreadLocalMap getMap(Thread t) {

        return t.threadLocals;

}

private T setInitialValue() {

        T value = initialValue();

        Thread t = Thread.currentThread();

        ThreadLocalMap map = getMap(t);

        if (map != null)

            map.set(this, value);

        else

//将当前ThreadLocal对象作为key构造ThreadLocalMap对象。

            createMap(t, value);

        return value;

}

void createMap(Thread t, T firstValue) {

        t.threadLocals = new ThreadLocalMap(this, firstValue);

}

static class ThreadLocalMap {

    private static final int INITIAL_CAPACITY = 16;

private Entry[] table;

static class Entry extends WeakReference<ThreadLocal<?>> {

              Object value;

            Entry(ThreadLocal<?> k, Object v) {

                super(k);

                value = v;

            }

        }

}

public void set(T value) {

①第一步拿到当前的线程

        Thread t = Thread.currentThread();

    ②拿到当前的线程的ThreadLocalMap成员变量

        ThreadLocalMap map = getMap(t);

    ③将值设置到key为当前threadlocal对象,value就是传入的参数的ThreadLocalMap中。若ThreadLocalMap对象不存在那么要进行初始化。

        if (map != null)

            map.set(this, value);

        else

            createMap(t, value);

 }

public void remove() {

//拿到当前线程的ThreadLocalMap成员变量

         ThreadLocalMap m = getMap(Thread.currentThread());

         if (m != null)

//将ThreadLocalMap数组中当前ThreadLocal对象对应下标索引处的对象设置为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) {

                    e.clear();

                    expungeStaleEntry(i);

                    return;

                }

            }

        }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值