ThreadLocal,即線程本地變量或線程本地存儲。
Threadlocal相當於一個容器,用於存放每個線程的局部變量,這種變量在線程的生命周期內起作用,減少同一個線程內多個函數或組件之間一些公共變量傳遞的復雜度。Threadlocal實例通常來說都是public static類型的。Threadlocal可以給一個初始值,而每個線程都會獲得這個初始值的一個副本,這樣才能保證不同的線程都有一份拷貝。
一般情況下,通過Threadlocal.set()到線程中的對象是該線程自己使用的對象,其他線程是訪問不到的,各個線程中訪問的是不同的對象。如果Threadlocal.set()進去的東西本來就是多個線程共享的同一個對象,那么多個線程的Threadlocal.get()取得的還是這個共享對象本身,還是有並發訪問問題。
向Threadlocal中的set的變量是由Thread線程對象自身保存的,當用戶調用Threadlocal對象的set(Object o)時,該方法則通過Thread.currentThread()獲取當前線程,將變量存入線程中的ThreadlocalMap類的對象內,Map中元素的鍵為當前的Threadlocal對象,而值對應線程的變量副本。
ThreadLocalMap(就是線程中的一個屬性)
每個線程中都有一個自己的ThreadLocalMap類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。
將一個共用的Threadlocal靜態實例作為key,將不同對象的引用保存到不同線程的ThreadLocalMap中,然后在線程執行的各處通過這個靜態Threadlocal實例的get()方法取得自己線程保存的那個對象,避免了將這個對象作為參數傳遞的麻煩。
ThreadLocalMap其實就是線程里面的一個屬性,他在thread類中定義。
ThreadLocal.ThreadLocalMap threadLocals=null;
public T get(){ Thread t = Thread.currentThread();//每個Thread對象內部保存一個ThreadlocalMap對象。
ThreadlocalMap map = getMap(t);//map重元素的鍵為共用的Threadlocal對象,而值為對應線程的變量副本。
if(map != null) return (T)map.get(this); T value = initialValue(); createMap(t,value); return value; } public void set(T value){ Thread t = Thread.currentThread(); ThreadlocalMap map = getMap(t); if(map != null) map.set(this,value); else createMap(t,value); } ThreadlocalMap getMap(Thread t){ return t.threadLocals; } void createMap(Thread t, T firstValue){ t.threadLocals = new ThreadlocalMap(this,firstValue); }
使用場景:
最常見的threadlocal使用場景是用來解決數據庫連接、session管理等。
1 private static final ThreadLocal threadSession = new ThreadLocal(); 2 public static Session getSession() throws InfrastructureException { 3 Session s = (Session) threadSession.get(); 4 try { 5 if (s == null) { 6 s = getSessionFactory().openSession(); 7 threadSession.set(s); 8 } 9 } catch (HibernateException ex) { 10 throw new InfrastructureException(ex); 11 } 12 return s; 13 }