? ? 1、ThreadLocal線程的局部變量。既然是線程局部變量,那么理所當然就應該存儲在自己的線程對象中,我們可以從 Thread 的源碼中找到線程局部變量存儲的地方:

我們可以看到線程局部變量是存儲在Thread對象的 threadLocals 屬性中,而 threadLocals 屬性是一個 ThreadLocal.ThreadLocalMap 對象。
2、ThreadLocalMap是什么呢?

可以看到他是ThreadLocal的一個靜態(tài)內部類,內部是一個自己實現(xiàn)的以ThreadLocal為key值的map,使用了弱引用的方式。方便內存的回收。

從構造函數(shù)中可以看出,他是一個 private Entry[] table數(shù)組,通過firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1)實現(xiàn)key到value的映射,初始化大小為16。

threadLocalHashCode 是一個原子變量每次增加0x61c88647實現(xiàn),然后?& (INITIAL_CAPACITY - 1)?取得在數(shù)組?private?Entry[] table?中的索引。
3、ThreadLocal初始化


首先在當前線程中獲取threadLoals,如果為null,則進行初始化工作。


4、內存的回收
ThreadLocal 涉及到的兩個層面的內存自動回收
????當線程死亡時,那么所有的保存在的線程局部變量就會被回收,其實這里是指線程Thread對象中的 ThreadLocal.ThreadLocalMap threadLocals 會被回收,這是顯然的。
如果線程可以活很長的時間,并且該線程保存的線程局部變量有很多(也就是 Entry 對象很多),那么就涉及到在線程的生命期內如何回收?ThreadLocalMap?的內存了,不然的話,Entry對象越多,那么ThreadLocalMap?就會越來越大,占用的內存就會越來越多,所以對于已經不需要了的線程局部變量,就應該清理掉其對應的Entry對象。使用的方式是,Entry對象的key是WeakReference 的包裝,當ThreadLocalMap?的?private Entry[] table,已經被占用達到了三分之二時 threshold = 2/3(也就是線程擁有的局部變量超過了10個) ,就會嘗試回收 Entry 對象,我們可以看到?ThreadLocalMap.set方法中有下面的代碼:
if?(!cleanSomeSlots(i, sz) && sz >= threshold)
????rehash();
5、 ThreadLocal常用的接口:
1)需要制定初始值時,可以覆蓋protected T initialValue()方法;
2)public T get();
3)public void set(T value);
4)public void remove();
6、總結
1)一個線程中的所有的局部變量其實存儲在該線程自己的同一個map屬性中;
2)線程死亡時,線程局部變量會自動回收內存;
3)線程局部變量時通過一個 Entry 保存在map中,該Entry 的key是一個 WeakReference包裝的ThreadLocal, value為線程局部變量;?
???? key 到 value 的映射是通過:ThreadLocal.threadLocalHashCode & (INITIAL_CAPACITY - 1) 來完成的;
4)當線程擁有的局部變量超過了容量的2/3(沒有擴大容量時是10個),會涉及到ThreadLocalMap中Entry的回收;