Java多线程之——ThreadLocal

ThreadLocal是什么:每一个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);
}

参数是我们要存的值 Object

第一步取到当前线程

第二步有一个方法getMap,点进去看(ps:准备好转圈圈哦~),顺便看一下Thread类的一个属性

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
 * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

这个方法是取到了Thread类的一个实例变量ThreadLocalMap,而ThreadLocalMap是ThreadLocal的一个内部类

向下看,如果map是空,那么已当前对象为k,当前对象就是ThreadLocal啊,参数为值存进map,就是说ThreadLocalMap的键是外部类ThreadLocal,值是我们存的Object。

简单说,线程有一个实例属性ThreadLocalMap,map键是外部类ThreadLocal,值是存放的Object。

第三步方法createMap

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

创建当前线程的ThreadLocalMap并存放值

其实到这里,已经对ThreadLocal了解的差不多了,本身是键,而一个键只能对应一个值,所以肯定不会互相影响啦。

get/remove方法

remove方法

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

取出当前线程的ThreadLocalMap。如果存在,移除当前ThreadLocal为键的键值对

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();
}

就简单说了,取出当前线程的ThreadLocalMap,

如果map不为空取出当前ThreadLocal的Entry对象,取出entry对象的值返回

如果为空返回方法setInitialValue()

看方法

private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

第一步方法initialValue()

protected T initialValue() {
    return null;
}

返回一个null

下面的就和之前的差不多了就不赘述了,最后返回null。

这里说一个我之前看到的ThreadLocal的‘坑’

如果我们项目使用的是线程池,我们知道线程池可能不会轻易关掉线程,也就是说对应的ThreadLocalMap一旦创建,如果不加处理,他的生命周期和Thread是一致的,那么存储的ThreadLocal对象的生命周期就不得而知了,久而久之,这个ThreadLocalMap越来越大,,会发生什么,就不得而知了...

记录到此

猜你喜欢

转载自blog.csdn.net/java_ying/article/details/81287693