對執行緒本地變數的理解,將登入資訊存放到執行緒本地變數中
阿新 • • 發佈:2018-12-14
在獲取使用者的登入資訊時,我們一般從ThreadLocalMap中獲取,ThreadLocalMap中存放的變數就是執行緒本地的變數,是執行緒隔離的,使用執行緒本地變數而非區域性變數的原因:方便我們對這些變數統一管理,免去頻繁地傳參。
ThreadLocal 原理:實質上,執行緒本地變數並不是儲存在ThreadLocal中,而是存放在ThreadLocalMap中,ThreadLocalMap是ThreadLocal中的一個靜態內部類,我們檢視ThreadLocal的set(T value)原始碼可以看到:
ThreadLocal執行set方法其實是當前執行緒的ThreadLocalMap物件執行set方法,key是執行緒的ThreadLocal物件,如果這個執行緒沒有ThreadLocalMap物件則為它建立一個
這裡我們需要注意一下getMap方法,這是獲取ThreadLocalMap。
我們再看一下ThreadLocalMap的鍵值對和它的set方法,首先是ThreadLocalMap的鍵值對接點Entry,通過原始碼得知它是一個鍵為ThreadLocal,值為Object物件的弱引用。
圖為Entry的繼承關係和建構函式
由於每個執行緒擁有不同的ThreadLocalMap物件,所以每個節點的資料是執行緒隔離的,每個執行緒對ThreadLocalMap的操作只能操作自己的變數。至於為什麼Entry的key要繼承弱引用呢:防止執行緒銷燬後,key一直不被回收造成記憶體洩漏
通過程式碼實現將資料放入執行緒本地變數
、
/** * 將變數存到他自己的執行緒本地變數 * * */ class ThreadLocalUtil{ ThreadLocalUtil(){ } /** * 建立threadLocal物件 規定存入ThreadLocal中的資料型別 * */ public static final ThreadLocal<HashMap<String,Object>> threadLocal=new ThreadLocal<HashMap<String,Object>>(); public static HashMap<String,Object> get(){ return threadLocal.get(); } public static void set(HashMap<String,Object> payLoad) { threadLocal.set(payLoad); } public static void remove() { threadLocal.remove(); } } class TeatThread extends Thread{ @Override public void run() { // TODO Auto-generated method stub HashMap<String,Object> map=new HashMap<String,Object>(); map.put(Thread.currentThread().getName(),Thread.currentThread().getName()+ "value"); ThreadLocalUtil.set(map); System.err.println(Thread.currentThread().getName()+"------"+ThreadLocalUtil.get().get(Thread.currentThread().getName())); } } public class hellojava { public static void main(String[] args) { TeatThread t1=new TeatThread(); t1.setName("t1"); TeatThread t2=new TeatThread(); t1.setName("t2"); t1.start(); t2.start(); } }