ThreadLocal

ThreadLocal是什么

ThreadLocal是一个关于创建线程局部变量的类。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

本文需要解决一下几个问题

  • 每个线程的变量副本是存储在哪里的?

  • 变量副本是怎么从共享的那个变量赋值出来的?源码中的threadlocal的初始值是什么时机设置的?

  • ThreadLocal是如何实现了多个线程之间每个线程一个变量副本的?它是如何实现共享变量的。

ThreadLocal机制主要由Entry、ThreadLocalMap、Thread、ThreadLocal这四个类相互协作实现的。


我们来看set()方法

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

这个方法用当前线程t,去获取实体map,并set,如果没有则Creat


我们再来看get()方法

    public T get() {
        Thread t = Thread.currentThread();
        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();
    }

同set方法差不多

我们来看看**ThreadLocalMap **

//初始化大小
private static final int INITIAL_CAPACITY = 16;
//容器为数组
private Entry[] table;

Entry

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

    Entry(ThreadLocal k, Object v) {
        super(k);
        value = v;
    }
}

Entry的定义很简单,它扩展自ThreadLocal类型的WeakReference类,是一个key-value对类。key是ThreadLocal对象的弱引用,value是线程的内部变量。

Entry使用弱引用作为key目的是,希望在外部不再需要访问ThreadLocal对象时可以让GC尽快地回收对象,而不必等到线程结束后。

当GC回收ThreadLocal对象后,再通过Entry.get()获取ThreadLocal对象时返回null,这使得内部能够感知什么时候不需要再持有对value的引用,从而释放Entry对象的引用,进而释放value的引用,这时如果value在外部没有任何引用的话(通常你不应该在外部持有对value的引用),随后被GC回收。这种感知和释放的行为发生在ThreadLocal的get、set、remove操作时。


通常在Java的世界里,我们不需要关系对象的释放,大部分情况下GC会自动帮我们回收。

但是如果使用ThreadLocal不当,是有可能导致内存泄漏的。

ThreadLocal释放内部变量通常在以下时机:

线程结束后
显式调用remove
在调用get、set时,如果探测到ThreadLocal对象的弱引用对象get返回null顺便释放。
所以,如果线程存活的生命周期很长,特别是和进程一样长的话,就要特别注意防止ThreadLocal引入内存泄漏的风险,在不需要再使用某个线程内部变量时记得显式调用remove清理掉。

参考
理解ThreadLocal
理解Java中的ThreadLocal

你可能感兴趣的:(ThreadLocal)