Thread類中有一個threadLocals變量,類型為ThreadLocalMap
public class Thread {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocalMap對key的引用是弱引用,對value的引用是強(qiáng)引用。
假設(shè)我們在一個方法內(nèi)定義了一個ThreadLocal局部變量,在方法運行過程中,這個ThreadLocal變量同時持有2個引用:
- java虛擬機(jī)棧的局部變量表對ThreadLocal變量的強(qiáng)引用
- ThreadLocalMap對ThreadLocal變量的弱引用
單條引用鏈的可達(dá)性以最弱的引用類型決定,多條引用鏈的可達(dá)性以最強(qiáng)的引用類型決定,因此方法運行過程中,ThreadLocal變量擁有強(qiáng)引用,不會被垃圾回收。
當(dāng)方法運行結(jié)束后,ThreadLocal變量僅剩ThreadLocalMap對它的虛引用,隨時可能被垃圾回收掉。
當(dāng)ThreadLocal對象被回收之后,ThreadLocalMap里key為null,value不為null,但是只要Thread類還在運行,ThreadLocalMap對value的強(qiáng)引用就有效,因此value不會被自動回收。
因此,當(dāng)我們使用完ThreadLocal之后,需要手動remove掉,remove方法里會把value設(shè)置為null。
為什么ThreadLocaMap對value的引用不做成弱引用?
- key,除了ThreadLocaMap的弱引用,可能還會有ThreadLocal的強(qiáng)引用(方法還沒運行結(jié)束時),只要后者還在,Key就不會被回收。
- value只有ThreadLocaMap的引用,如果value是弱引用,那隨時會被回收,ThreadLocal就沒法用了。