threadlocal是用來儲存執行緒的本地資料的。
threadlocal的設計算是十分巧妙的。
每乙個執行緒thread持有threadlocalmap, threadlocalmap是threadlocal下的乙個內部靜態類。threadlocalmap並沒有繼承map, 而是持有了乙個entry的table。entry的key是threadlocal (弱引用), value是儲存的值。
來看一下threadlocal的set方法:
public void set(t value)
跟進,看一下threadlocalmap的set方法:
private void set(threadlocal> key, object value)
//如果當前這個的 entry 是乙個陳舊entry(有物件但是k == null),
//那就呼叫 replacestaleentry(key, value, i);將資料儲存進去,並結束
if (k == null)
}tab[i] = new entry(key, value);
int sz = ++size;
// 清除部分的陳舊entry,如果清除不成功,
//並且大於等於負載閾值 threshold (當前size的2/3)的時候就會 rehash
if (!cleansomeslots(i, sz) && sz >= threshold)
rehash();
}
先來看下replacestaleentry這個方法:
private void replacestaleentry(threadlocal> key, object value,
int staleslot)
//如果在查詢過程中還未發現髒entry,那麼就以當前位置作為cleansomeslots的起點
if (k == null && slottoexpunge == staleslot)
slottoexpunge = i;
}// 如果在查詢過程中沒有找到可以覆蓋的entry,則將新的entry插入在髒entry
tab[staleslot].value = null;
tab[staleslot] = new entry(key, value);
// 如果找到了,清理
if (slottoexpunge != staleslot)
cleansomeslots(expungestaleentry(slottoexpunge), len);
}
作者認為在髒key的附近髒key是聚集的,那麼在當前key是存在key為null,value不為null的情況下,向前尋找到key不為null的節點,然後向後遍歷進行區域性清理髒key。
這樣不用進行遍歷全部資料,同時也可以進行一部分的髒key的清理,但終究出現記憶體洩露時,節點越來越多,慢慢就清理不過來了。
private boolean cleansomeslots(int i, int n)
} while ( (n >>>= 1) != 0);
return removed;
}
可以看到, cleansomeslots這個看上去是log(n)的時間複雜度。但需要主要的是:一旦檢查到髒entry(key為null),n又會重新賦值為table的長度。
}相比於set()方法,get()方法就簡單很多了。
當我們呼叫threadlocal的get方法時,當table[i]不是和所要找的key相同的話,會繼續通過threadlocalmap的
getentryaftermiss方法向後環形去找:
public t get()
}return setinitialvalue();
}
private entry getentry(threadlocal> key)
private entry getentryaftermiss(threadlocal> key, int i, entry e)
return null;
}
private void remove(threadlocal> key) }}
我們知道threadlocalmap.entry的key是乙個弱引用。這就存在記憶體洩漏的問題,當key被**掉的時候,value一直得不到清除。
那為什麼仍要採用弱引用呢?
如果採用強引用,將threadlocal置為null的時候,因為threadlocalmap還強引用著threadlocal,造成threadlocal無法被**。
相比之下,採用弱引用,配合著上面get(), remove(), set()方法的**,是可以有效的解決記憶體洩漏的問題的。但前提是要使用這些方法!
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是乙個鍵值對的資料結構...