版權聲明:請尊重個人勞動成果,轉載注明出處,謝謝!http://blog.csdn.net/amazing7/article/details/51313851
線程局部變量,通路某個變量的每個線程都有自己的局部變量,它獨立于變量的初始化副本。
它的功用非常簡單,就是為每一個使用該變量的線程都提供一個變量值的副本,是每一個線程都可以獨立地改變自己的副本,而不會和其它線程的副本沖突。從線程的角度看,就好像每一個線程都完全擁有該變量。
threadlocal 執行個體通常是類中的 private static 字段,它們希望将狀态與某一個線程(例如,使用者 id 或事務 id)相關聯。每個線程都保持對其線程局部變量副本的隐式引用,隻要線程是活動的并且 threadlocal 執行個體是可通路的;線上程消失之後,其線程局部執行個體的所有副本都會被垃圾回收(除非存在對這些副本的其他引用)。
protected t initialvalue() :傳回此線程局部變量的初始值
線程第一次使用 get() 方法通路變量時将調用此方法,但如果線程之前調用了 set(t) 方法,則不會對該線程再調用 initialvalue 方法。通常,此方法對每個線程最多調用一次,但如果在調用 get() 後又調用了 remove(),則可能再次調用此方法。
該實作傳回 null;如果程式員希望線程局部變量具有 null 以外的值,則必須為 threadlocal 建立子類,并重寫此方法。通常将使用匿名内部類完成此操作。
public t get() :傳回此線程局部變量的目前線程的值
如果變量沒有用于目前線程的值,則先将其初始化為調用 initialvalue() 方法傳回的值。
public void set(t value) :将此線程局部變量的目前線程副本中的值設定為指定值
大部分子類不需要重寫此方法,它們隻依靠 initialvalue() 方法來設定線程局部變量的值。
public void remove() :移除此線程局部變量目前線程的值
如果此線程局部變量随後被目前線程 讀取,且這期間目前線程沒有 設定其值,則将調用其 initialvalue() 方法重新初始化其值。這将導緻在目前線程多次調用 initialvalue 方法。
如果希望線程局部變量初始化其它值,那麼需要自己實作threadlocal的子類并重寫該方法,通常使用一個内部類對threadlocal進行執行個體化。
比如下面的例子,serialnum類為每一個類配置設定一個序号:
先看看threadlocal類的部分源碼:
我們可以很明顯的看出threadlocal把線程和線程局部變量存在threadlocalmap中,而threadlocalmap是threadlocal的靜态類部類,我們來看看threadlocalmap 的部分源碼:
這個map的key是threadlocal對象的弱引用,當要抛棄掉threadlocal對象時,垃圾收集器會忽略這個key的引用而清理掉threadlocal對象 。
那麼到底是threadlocal還是thread持有threadlocalmap對象的引用呢?
我們在thread源碼中發現:
threadlocalmap變量屬于thread的内部屬性,不同的thread擁有完全不同的threadlocalmap變量.
thread中的threadlocalmap變量的值是在threadlocal對象進行set或者get操作時建立的.
在建立threadlocalmap之前,會首先檢查目前thread中的threadlocalmap變量是否已經存在,如果不存在則建立一個;如果已經存在,則使用目前thread已建立的threadlocalmap.
從上面的分析我們可以得出:
因為每個thread在進行對象通路時,通路的都是各自線程自己的threadlocalmap,是以保證了thread與thread之間的資料通路隔離。
不同的threadlocal執行個體操作同一thread時,threadlocalmap在存儲時采用目前threadlocal的執行個體作為key來保證資料通路隔離(上面源碼entry處可以看出)。
舉個例子說明:
輸出結果為:
同步機制采用了“以時間換空間”的方式,提供一份變量,讓不同的線程排隊通路.而threadlocal采用了“以空間換時間”的方式,為每一個線程都提供一份變量的副本,進而實作同時通路而互不影響。
而threadlocal會為每一個線程維護一個和該線程綁定的變量的副本,進而隔離了多個線程的資料,每一個線程都擁有自己的變量副本,進而也就沒有必要對該變量進行同步了。
同步機制是為了同步多個線程對相同資源的并發通路,是為了多個線程之間進行通信的有效方式。
而threadlocal是隔離多個線程的資料共享,從根本上就不在多個線程之間共享資源(變量),這樣當然不需要對多個線程進行同步了。
是以,如果你需要進行多個線程之間進行通信,則使用同步機制。如果需要隔離多個線程之間的共享沖突,可以使用threadlocal。