在多執行緒的情況下,threadlocal提供了乙個種為每個執行緒訪問相同的變數,並且執行緒對變數的更新互不影響的機制。也是物件實現執行緒安全的一種方式。
我們常用的方法有get
、set
和initialvalue
,這次將會圍繞這幾個方法的原始碼進行深入解析
// 獲取元素
public t get()
}// 返回initialvalue的值
return setinitialvalue();
}
首先,通過當前執行緒物件獲取threadlocalmap
物件,然後以threadlocal
物件自身為key獲取threadlocalmap.entry
,最後在獲取entry
中的value
**的邏輯非常簡單,我們再來看看getmap
和map.getentry
方法
getmap方法
threadlocalmap getmap(thread t)
threadlocals
是thread的乙個屬性
public class thread implements runnable
map.getentry方法
threadlocalmap
是threadlocal
物件的乙個內部類,entry
是threadlocalmap
的乙個內部類
// threadlocal的內部類
static class threadlocalmap
}// entry陣列,用來存放乙個執行緒的多個threadlocal變數
private entry table;
// 根據threadlocal來獲取對應的value
private entry getentry(threadlocal> key)
}
當key
過期了如何獲取值
private entry getentryaftermiss(threadlocal> key, int i, entry e)
return null;
}
public void set(t value)
先獲取threadlocalmap
物件,然後在以threadlocal
為key
,將value
設定到threadlocalmap
物件中
map.set方法
// 將threadlocal對應的value儲存到threadlocalmap物件中
private void set(threadlocal> key, object value)
// 去掉過期的threadlocal物件
if (k == null)
}// entry陣列中不存在threadlocal物件,建立乙個新的entry物件
tab[i] = new entry(key, value);
int sz = ++size;
// 清除過期的物件
if (!cleansomeslots(i, sz) && sz >= threshold)
// entry陣列的大小改變以後重新計算hash
rehash();
}
createmap方法
void createmap(thread t, t firstvalue)
// 可以通過重寫該方法來返回預設值
protected t initialvalue()
首先看一下threadlocal中物件的引用關係圖
從threadlocal中物件的引用關係來看,thread
、threadlocalmap
、entry
物件之間都是強引用,如果可能出現記憶體洩漏那就是threadlocal
物件弱引用引起的。
什麼時候會發生記憶體洩漏
當threadlocal
例項不在有強引用指向,只有弱引用存在,且gc**了這部分空間時,也就是entry
物件中的key
被**了,但是value還沒有被**,這時會出現記憶體洩漏,因為value
無法得到釋放。
如何避免記憶體洩漏
threadlocalmap
中是通過expungestaleentry
將key
為null
的物件對應的value
也設定為null
private int expungestaleentry(int staleslot) else }}
return i;
}
所以只要呼叫expungestaleentry
方法,且key
為null
時就可以**掉value
了,我們可以通過呼叫threadlocal
的remove
方法進行釋放
避免threadlocal出現記憶體洩漏的方式有:
呼叫threadlocal
的remove
方法
將threadlocal
變數定義成static
型別的,對threadlocal
的強引用不會消失,所以也不存在記憶體洩漏的問題,但是可能會有所浪費
ThreadLocal原始碼理解
threadlocal其實原理是建立了多份相同資料儲存在堆記憶體上,每個執行緒的thread類裡有threadlocal.threadlocalmap threadlocals的屬性來指向存位置,所以每個執行緒修改都不會影響到其他執行緒的資料 首先說下下面用到的東西 threadlocalmap為t...
ThreadLocal原始碼分析
在理解handler looper之前,先來說說threadlocal這個類,聽名字好像是乙個本地執行緒的意思,實際上它並不是乙個thread,而是提供乙個與執行緒有關的區域性變數功能,每個執行緒之間的資料互不影響。我們知道使用handler的時候,每個執行緒都需要有乙個looper物件,那麼and...
ThreadLocal 原始碼解讀
在正式讀 前先簡單介紹threadlocal的實現方式。每個執行緒都會有乙個threadlocalmap,只有在使用到threadlocal的時候才會初始化threadlocalmap。需要儲存的物件t會被放到entry裡面儲存在threadlocalmap的陣列中,entry是乙個鍵值對的資料結構...