ThreadLocal介绍和源码解析
????????????????ThreadLocal類被稱為線程本地變量類或者線程局部變量類。如果程序創建了一個ThreadLocal實例,那么在訪問這個變量的值時,每個線程都會擁有一個獨立的、自己的本地值。當線程各自操作自己的本地變量時,從而實現了線程安全。
?1.ThreadLocal類 :
//無參 ThreadLocal<String> threadLocal = new ThreadLocal<>(); //靜態方法 withInitial 全部線程可見 ThreadLocal<String> stringThreadLocal = ThreadLocal.withInitial(() -> "ok");? ? ? ? ? ? ? ? ? ? ? ?1.1私有的靜態內部類 ThreadLocalMap
//看出Thread線程類中有個屬性threadLocals class Thread {//屬性,存儲threadLocalThreadLocal.ThreadLocalMap threadLocals = null;... } class ThreadLocalMap{//有兩個構造方法ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue);ThreadLocalMap(ThreadLocalMap parentMap);//儲存值(重要) Entry類為ThreadLocalMap的內部類,Entry(ThreadLocal<?> k, Object v) k為虛 //引用。其中value和T referent兩個屬性,value儲存值,referent為ThreadLocalprivate Entry[] table; }? ? ? ? 分析ThreadLocal類中的set(T value) 方法
public void set(T value) {//1. 由Thread類的靜態方法currentThread(),獲取當前線程的實例tThread t = Thread.currentThread();//2. 根據線程實例t,得到當前線程的Thread.threadLocals屬性ThreadLocalMap mapThreadLocalMap map = getMap(t);//3.判斷map!=null,進入ThreadLocalMap類的set方法if (map != null)//3.1進入ThreadLocalMap類的set方法map.set(this, value);else//4.1 進入createMap方法createMap(t, value); } set(ThreadLocal<?> key, Object value) {// 3.2 ThreadLocalMap.table屬性賦值tabEntry[] tab = table;// 3.3 得到tab的大小 tab初始大小為16int len = tab.length;// 3.4 key.threadLocalHashCode的二進制 & 1111(15) 0<=i<=15 int i = key.threadLocalHashCode & (len-1);// 3.5 i假定3, for語句的初始tab[3],當tab[i]==null結束循環,當i=15時,返回i=0for (Entry e = tab[i];e != null;e = tab[i = nextIndex(i, len)]) {//3.6 從Entry中得到,當前threadLocal對象ThreadLocal<?> k = e.get();//3.7 當前threadLocal對象與this相同,覆蓋之前的值if (k == key) {e.value = value;return;}// 3.8 當前threadLocal對象為nullif (k == null) {//清除無效的entryreplaceStaleEntry(key, value, i);return;}}// 3.9 i=3 ,tab[3]=new Entry(key,value)tab[i] = new Entry(key, value);// 3.10 tab為10時,重hash,擴容int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); } void createMap(Thread t, T firstValue) {// 4.2 ThreadLocalMap雙參構造賦值給當前線程類的屬性threadLocalst.threadLocals = new ThreadLocalMap(this, firstValue); }???分析ThreadLocal類中的get()方法?
public T get() {// 1.獲取當前線程對象的實例Thread t = Thread.currentThread();// 2.得到線程實例的threadLocals屬性ThreadLocalMap map = getMap(t);// 3.map為not nullif (map != null) {// 3.1.得到當前ThreadLocal對象的EntryThreadLocalMap.Entry e = map.getEntry(this);// 3.2 Entry對象不為空if (e != null) {@SuppressWarnings("unchecked")// 3.3 得到Entry對象的value值,返回 T result = (T)e.value;return result;}}// 4.會調用SuppliedThreadLocal類重寫的initialValue()方法,返回value,并且會將該值和當 // 前的Threadlocal對象儲存到當前線程的threadLocals中return setInitialValue(); }? ? ? ? ? ? ? ThreadLocal對象。1,線程安全,不需要加鎖,避免鎖的開銷。2,節省內存。因為線程儲存對象值,因此對象與線程的生命周期相同。3,線程隔離。
? ? ? ? ? ? ?使用時1.用static final 修飾 2.使用結束后調remove()方法。
? ? ? ? ? ? ?應用。1.從數據庫的connection對象,放到ThreaLocal。2.RequestContextHolder。將requesFadce放到放到ThreaLocal中。3.session對象或token(攜帶用戶基本信息)放在ThreaLocal。4.ThreadLocalSecurityContextHolderStrategy。將SecurityContextImpl對象放到了ThreadLocal。5.SimpleDateFormat(線程不安全)。
總結
以上是生活随笔為你收集整理的ThreadLocal介绍和源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (1)英特尔工业边缘洞见平台(EII)安
- 下一篇: PTA数据结构题目