1. 程式人生 > >對執行緒本地變數的理解,將登入資訊存放到執行緒本地變數中

對執行緒本地變數的理解,將登入資訊存放到執行緒本地變數中

      在獲取使用者的登入資訊時,我們一般從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();
		}
}