首先說明ThreadLocal存放的值是線程内共享的,線程間互斥的,主要用于線程内共享一些資料,避免通過參數來傳遞,這樣處理後,能夠優雅的解決一些實際問題,比如Hibernate中的OpenSessionInView,就是使用ThreadLocal儲存Session對象,還有我們經常用ThreadLocal存放Connection,代碼如:
這樣處理的好處:
統一管理Connection;
不需要顯示傳參Connection,代碼更優雅;
降低耦合性。
ThreadLocal有四個方法,分别為:
傳回此線程局部變量的目前線程的初始值。最多在每次通路線程來獲得每個線程局部變量時調用此方法一次,即線程第一次使用 <code>get()</code> 方法通路變量的時候。如果線程先于 get 方法調用 <code>set(T)</code> 方法,則不會線上程中再調用 initialValue 方法。
該實作隻傳回 null;如果程式員希望将線程局部變量初始化為 null 以外的某個值,則必須為 ThreadLocal 建立子類,并重寫此方法。通常,将使用匿名内部類。initialValue 的典型實作将調用一個适當的構造方法,并傳回新構造的對象。
傳回:傳回此線程局部變量的初始值
傳回此線程局部變量的目前線程副本中的值。如果這是線程第一次調用該方法,則建立并初始化此副本。
傳回:此線程局部變量的目前線程的值
将此線程局部變量的目前線程副本中的值設定為指定值。許多應用程式不需要這項功能,它們隻依賴于 <code>initialValue()</code> 方法來設定線程局部變量的值。
參數:<code>value</code> - 存儲在此線程局部變量的目前線程副本中的值。
移除此線程局部變量的值。這可能有助于減少線程局部變量的存儲需求。如果再次通路此線程局部變量,那麼在預設情況下它将擁有其 initialValue。
很多人對ThreadLocal存在一定的誤解,說ThreadLocal中有一個全局的Map,set時執行map.put(Thread.currentThread(), value),get和remove時也同理,但SUN的大師們是否是如此實作的,我們隻能去看源碼了。
set方法:
這裡注意,ThreadLocal中是有一個Map,但這個Map不是我們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個内部類,不對外使用的。當使用ThreadLocal存值時,首先是擷取到目前線程對象,然後擷取到目前線程本地變量Map,最後将目前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal對象, 存放的值],這樣做的好處是,每個線程都對應一個本地變量的Map,是以一個線程可以存在多個線程本地變量。
get方法:
有了之前set方法的分析,get方法也同理,需要說明的是,如果沒有進行過set操作,那從ThreadLocalMap中拿到的值就是null,這時get方法會傳回初始值,也就是調用initialValue()方法,ThreadLocal中這個方法預設傳回null。當我們有需要第一次get時就能得到一個值時,可以繼承ThreadLocal,并且覆寫initialValue()方法。
(完)