1. 程式人生 > >Java多執行緒之——ThreadLocal

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越來越大,,會發生什麼,就不得而知了...

記錄到此