ThreadLocal的解析

ThreadLocal的使用

是线程私有的,那么必然是线程安全的,使用ThreadLocal实现线程本地存储的功能,也就是说我有个变量需要被一个线程独享,并且可以随时取用,那么ThreadLocal是一个很好的选择,比如在web开发中使用ThreadLocal存储User信息,方便随时调用,线程内部随时可以调用,相当于车子后面的后备箱。

  • 看看ThreadLocal的源码:
public void set(T value) {
        //取得当前线程对应的map
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //如果map != null this为key
        if (map != null)
            map.set(this, value);
        else
            /**否则
            void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    } */
            createMap(t, value);
    }

public T get() {
        //首先取得当前线程
        Thread t = Thread.currentThread();
        //Thread类定义了一个map,ThreadLocal.ThreadLocalMap threadLocals = null;
        //thread上面挂了一个map,取得这个map
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            //如果map != null ,取出this对应的entry
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                //取出存储数据
                return result;
            }
        }
        return setInitialValue();
    }

####ThreadLocal如何退出呢?
了解ThreadLocal的内部实现后,ThreadLocal是Thread类内部定义的,也就意味着ThreadLocal的生命周期和线程是相同的,线程不退出,那么ThreadLocal就无法被回收。
> - 线程退出的时候:
ThreadLocal如何退出呢?

了解ThreadLocal的内部实现后,ThreadLocal是Thread类内部定义的,也就意味着ThreadLocal的生命周期和线程是相同的,线程不退出,那么ThreadLocal就无法被回收。

  • 线程退出的时候:
private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        /* Aggressively null out all reference fields: see bug 4006245 */
        target = null;
        /* Speed the release of some of these resources */
        threadLocals = null;
        //这个地方为什么可以释放ThreadLocal资源,比较它存放在map里面,为什么可以像普通资源一样被释放?弱引用。
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

ThreadLocalMap使用了弱引用,也就是在map中存储的key不是直接持有引用,所以一旦外部直接引用被置为null,key会变成null,那么map中的value就会被GC回收。

static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
那么如果线程不关闭呢?比如线程池,如果线程一直没有exit,那么不同的对象调用,每个都会在ThreadLocalMap中维持一个entry,那么多来几次,可能会出现内存泄漏,那么如何处理?ThreadLocal.remove()方法可以实现这一点。
/**
         * Remove the entry for key.
         */
        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;
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值