ThreadLcoal

ThreadLocal

	当使用ThreadLocal维护变量时,ThreadLocal为每个使用改变量的线程创建独立的变量副本;
	每个线程可以操作属于自己的副本,不会对其他线程的副本产生干扰。以空间换时间的方式,使得访问并行化,对象共享化。
//get()方法:返回此ThreadLcoal变量的当前线程副本中的值
public T get() {
        Thread t = Thread.currentThread();
        //不论是get还是set操作,第一件事就是从Thread中找到相对应的ThreadLocalMap,即获取当前thread对应的ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                T result = (T)e.value;
                return result;
            }}
        return setInitialValue();
    }
    
 // getMap()
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
 //ThreadLocalMap真正的引用是在Thread类中  
ThreadLocal.ThreadLocalMap threadLocals = null;

###ThreadLocalMap

//ThreadLocalMap继承了WeakReference.ThreadLocalMap以ThreadLcoal这个弱引用作为key,那么在系统gc后,ThreadLcoal被回收,ThreadLocalMap中可能会存在key==null的value,如果创建ThreadLocal的线程一直在运行,且value无法访问,就会造成内存泄露。

Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
//仅以getEntry()方法来查看ThreadLocalMapMap内部的处理内存泄露的方法
private Entry getEntry(ThreadLocal<?> key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            //根据下标直接获取e的值
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }

 private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
            Entry[] tab = table;
            int len = tab.length;
            while (e != null) {
                ThreadLocal<?> k = e.get();
                if (k == key)
                    return e;
                 //key==null时进行处理
                if (k == null)
                    expungeStaleEntry(i);
                else
                    i = nextIndex(i, len);
                e = tab[i];
            }
            return null;
        }
 //实际处理key==null的方法
private int expungeStaleEntry(int staleSlot) {
            Entry[] tab = table;
            int len = tab.length;

            // expunge entry at staleSlot
            tab[staleSlot].value = null;
            tab[staleSlot] = null;
            size--;

            // 再Hash处理
            Entry e;
            int i;
            for (i = nextIndex(staleSlot, len);(e = tab[i]) != null;i = nextIndex(i, len)) {
                ThreadLocal<?> k = e.get();
                //在key==null时,将value置为null,并且从table中删除
                if (k == null) {
                    e.value = null;
                    tab[i] = null;
                    size--;
                } else {
                    int h = k.threadLocalHashCode & (len - 1);
                    if (h != i) {
                        tab[i] = null;
                        while (tab[h] != null)
                            h = nextIndex(h, len);
                        tab[h] = e;
                    }
                }
            }
            return i;
        }



Hash冲突

	//ThreadLocalMap解决Hash冲突采用的是线性探测法。根据初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置。
private static int nextIndex(int i, int len) {
            return ((i + 1 < len) ? i + 1 : 0);
        }
        
 private static int prevIndex(int i, int len) {
            return ((i - 1 >= 0) ? i - 1 : len - 1);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值