ThreadLocal實現原理與原始碼分析

2021-09-23 18:39:57 字數 4241 閱讀 6120

threadlocal底層實現內部類:threadlocalmap

一、threadlocal的set方法原始碼分析:

(1)public void set(t value) {

thread t = thread.currentthread();

threadlocalmap map = getmap(t);

if (map != null)

map.set(this, value);

else

createmap(t, value);

1、thread t = thread.currentthread();

獲取當前執行緒物件t

2、threadlocalmap map = getmap(t);

獲取threadlocalmap物件,呼叫getmap方法,引數:thread t,將當前物件傳入到getmap方法,getmap的原始碼如(2)所示:

(2)threadlocalmap getmap(thread t) {

return t.threadlocals;

通過**分析得知:map的值是當前物件t中定義的threadlocalmap物件【也就是說map是屬於當前執行緒t中的屬性】。

3、如果map!=null,則執行map.set(this,value)。threadlocalmap中的key為threadlocal<?>物件。this將當前的threadlocal物件作為key。

4、如果map為null,則建立map,呼叫createmap(t,value),createmap原始碼如(3)所示:

(3)void createmap(thread t, t firstvalue) {

t.threadlocals = new threadlocalmap(this, firstvalue);

通過原始碼得知,初始化當前執行緒物件t的threadlocals例項。並且將value儲存到threadlocalmap中,將當前的threadlocal物件作為key。

注意:threadlocalmap例項是當前執行緒物件的屬性,並且threadlocalmap中的key是當前threadlocal物件。

二、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();

1、thread t = thread.currentthread();獲取當前執行緒物件t。

2、threadlocalmap map = getmap(t);通過以上原始碼得知,返回當前執行緒物件t的threadlocals例項。

(2-1)

private entry getentry(threadlocal<?> key) {

int i = key.threadlocalhashcode & (table.length - 1);

entry e = table[i];

if (e != null && e.get() == key)

return e;

else

return getentryaftermiss(key, i, e);

3.1、e.get() 呼叫的是weakreference中的get方法,返回的是threadlocal物件,即threadlocalmap的key值。

如果e.get()==key,則返回entry物件。否則,執行getentryaftermiss(key,i,e),原始碼如(2-2)

(2-2)

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;

if (k == null)

expungestaleentry(i);

else

i = nextindex(i, len);

e = tab[i];

return null;

3.2、如果e!=null,則執行e.get()獲取threadlocal物件k,

如果k==key,則返回e;

如果k==null,則執行expungestaleentry(i);//刪除過期的entry物件,【如果key為null,則entry物件為過期物件】

如果k!=null && k!=key,執行i=nextindex(i,len)則獲取tab[ ]陣列的下乙個索引,

e=tab[i]繼續從tab[ ]陣列中獲取entry物件e。執行3.2操作。

3.3、如果e!=null,則直接獲取e.value返回。如果e==null,則執行:setinitialvalue();

4、如果 map==null,則執行:setinitialvalue();原始碼(2-3)如下:

(2-3)

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;

(2-4)

protected t initialvalue() {

return null;

4.1、初始化value,執行initialvalue()方法,返回null。原始碼(2-4)

4.2、獲取當前執行緒物件t

4.3、呼叫getmap(t),獲取threadlocalmap物件。

4.4、如果map!=null,則執行map.set(this,value);否則,執行createmap(t,value),建立threadlocalmap,並且設定key與value。返回value。【value值為null】

三、原理

執行緒共享變數快取如下:

thread.threadlocalmap;

1、thread: 當前執行緒,可以通過thread.currentthread()獲取。

2、threadlocal:我們的static threadlocal變數。

3、object: 當前執行緒共享變數。

我們呼叫threadlocal.get方法時,實際上是從當前執行緒中獲取threadlocalmap,然後根據當前threadlocal獲取當前執行緒共享變數object。

threadlocal.set,threadlocal.remove實際上是同樣的道理。

這種儲存結構的好處:

1、執行緒死去的時候,執行緒共享變數threadlocalmap則銷毀。

2、threadlocalmap鍵值對數量為threadlocal的數量,一般來說threadlocal數量很少,相比在threadlocal中用map鍵值對儲存執行緒共享變數(thread數量一般來說比threadlocal數量多),效能提高很多。

關於threadlocalmap弱引用問題:

當執行緒沒有結束,但是threadlocal已經被**,則可能導致執行緒中存在threadlocalmap的鍵值對,造成記憶體洩露。(threadlocal被**,threadlocal關聯的執行緒共享變數還存在)。

雖然threadlocal的get,set方法可以清除threadlocalmap中key為null的value,但是get,set方法在記憶體洩露後並不會必然呼叫,所以為了防止此類情況的出現,我們有兩種手段。

1、使用完執行緒共享變數後,顯示呼叫threadlocalmap.remove方法清除執行緒共享變數;

2、jdk建議threadlocal定義為private static,這樣threadlocal的弱引用問題則不存在了。

ThreadLocal實現原理

threadlocal,即執行緒區域性變數,其實就是乙個容器,每個執行緒都可通過其set方法儲存乙份資料,並且在get時只會獲取自己執行緒的資料,是常用的實現執行緒安全的方式。自己用過許多次了,但沒有細究其原理,今天大概看了一下原始碼,算是明白了一點點0.0 直接看threadlocal的get方法...

ThreadLocal底層實現原理

解釋的不錯的一片文章 下邊是個人理解,如果有錯誤還請批評指正 首先說一下使用方式 threadlocalthreadlocala new threadlocal threadlocalthreadlocalb new threadlocal 存入 執行緒1 threadlocala.set aaa ...

ThreadLocal實現原理簡述

threadlocal是乙個執行緒內共享變數工具類。將執行緒與該執行緒存放的物件做乙個對映,各個執行緒之間的變數互不干擾。適用於各個執行緒依賴不同的變數值完成操作的場景,如 spring宣告式資料庫事務 shiro的session threadlocal內部結構 核心機制 1.每個執行緒例項中有個t...