日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ThreadLocal使用和原理

發布時間:2025/4/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadLocal使用和原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實現機制

1、每個Thread對象內部都維護了一個ThreadLocalMap這樣一個ThreadLocal的Map,可以存放若干個ThreadLocal。

/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;

2、當我們在調用get()方法的時候,先獲取當前線程,然后獲取到當前線程的ThreadLocalMap對象,如果非空,那么取出ThreadLocal的value,否則進行初始化,初始化就是將initialValue的值set到ThreadLocal中。

public T get() {//獲取當前線程Thread t = Thread.currentThread();//每個線程擁有一個map,取出來的是線程t的ThreadLocal.ThreadLocalMap對象

ThreadLocalMap map = getMap(t); if (map != null) {//this->ThreadLocal實例是作為map的key來使用的ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T)e.value;}//初始化這個線程的ThreadLocalMap,并且返回nullreturn setInitialValue();} private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;}protected T initialValue() {return null;}

3、當我們調用set()方法的時候,很常規,就是將值設置進ThreadLocal中。

public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)//一個thread.ThreadLocalMap 可以維護多個不同ThreadLocal的值map.set(this, value);elsecreateMap(t, value);}

事實上,從本質來講,就是每個線程都維護了一個map,而這個map的key就是threadLocal,而值就是我們set的那個值,每次線程在get的時候,都從自己線程的變量map中以ThreadLocal為key來取值,總體來講,ThreadLocal這個變量的狀態根本沒有發生變化,他僅僅是充當一個key的角色,另外提供給每一個線程一個初始值。

內存泄露

ThreadLocalMap使用ThreadLocal的弱引用作為key,如果一個ThreadLocal沒有外部強引用來引用它,那么系統 GC 的時候,這個ThreadLocal勢必會被回收,ThreadLocalMap中就會出現key為null的Entry,就沒有辦法訪問這些key為null的Entry的value,如果當前線程再遲遲不結束的話,這些key為null的Entry的value就會一直存在一條強引用鏈:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永遠無法回收,造成內存泄漏。

ThreadLocalMap的設計中已經考慮到這種情況,也加上了一些防護措施:在ThreadLocal的get(),set(),remove()的時候都會清除線程ThreadLocalMap里所有key為null的value。

為什么用弱引用?

key 使用強引用:引用的ThreadLocal的對象被回收了,但是ThreadLocalMap還持有ThreadLocal的強引用,如果沒有手動刪除,ThreadLocal不會被回收,導致Entry內存泄漏。

key 使用弱引用:引用的ThreadLocal的對象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使沒有手動刪除,ThreadLocal也會被回收。value在下一次ThreadLocalMap調用set,get,remove的時候會被清除,否則value內存溢出。

由于ThreadLocalMap的生命周期跟Thread一樣長,如果沒有手動刪除對應key,都會導致內存泄漏,但是使用弱引用可以多一層保障:弱引用ThreadLocal不會內存泄漏,對應的value在下一次ThreadLocalMap調用set,get,remove的時候會被清除。

使用舉例

public class TestThreadLocal {private static int j = 0;public static void main(String[] args) {final ThreadLocal<String> tl1 = new ThreadLocal<String>();final ThreadLocal<String> tl2 = new ThreadLocal<String>();ExecutorService es = Executors.newFixedThreadPool(10);for (int i = 0; i < 30; i++) {es.execute(new Runnable() {@Overridepublic void run() {synchronized (TestThreadLocal.class) {tl1.set("tl1"+"-"+j);tl2.set("tl2"+"-"+j);System.out.println("當前線程" + Thread.currentThread()+"-"+ j + "放入data=" + tl1.get());System.out.println("當前線程" + Thread.currentThread()+"-"+ j + "放入data=" + tl2.get());j++;}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("當前線程" + Thread.currentThread() + ":取出data=" + tl1.get());System.out.println("當前線程" + Thread.currentThread() + ":取出data=" + tl2.get());}});}} }

?

轉載于:https://www.cnblogs.com/wade-luffy/p/5755481.html

總結

以上是生活随笔為你收集整理的ThreadLocal使用和原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。