Java并發(fā)編程之ThreadLocal詳解
一、什么是ThreadLocal?
ThreadLocal
叫做線程本地變量,ThreadLocal
中填充的變量屬于當前線程,該變量對其他線程而言是隔離的。ThreadLocal
為變量在每個線程中都創(chuàng)建了一個副本,則每個線程都可以訪問自己內(nèi)部的副本變量。
二、ThreadLocal的使用場景
1.當對象進行跨層傳遞的時候,使用ThreadLocal
可以避免多層傳遞,打破層次間的約束。
2.線程間數(shù)據(jù)隔離。
3.進行事務(wù)操作,用于存儲線程事務(wù)信息。
4.數(shù)據(jù)庫連接,Session會話管理。
三、如何使用ThreadLocal
ThreadLocal
的作用是每一個線程創(chuàng)建一個副本。
從以上實例中可以看出,每一個線程都有自己的local
值,設(shè)置一個休眠時間就是為了另外一個線程也能夠及時的讀取當前的local
值。
四、數(shù)據(jù)庫連接時的使用
上面是一個數(shù)據(jù)庫連接的管理類,使用數(shù)據(jù)庫的時候首先就是建立數(shù)據(jù)庫連接,然后用完之后進行關(guān)閉,這里存在一個問題:如果1個客戶端頻繁的使用數(shù)據(jù)庫,那么就需要建立多次連接和關(guān)閉,這樣服務(wù)器可能會吃不消,如果有一萬個客戶端,服務(wù)器的壓力更大。
這個時候就可以使用ThreadLocal
,他會在每個線程中對連接創(chuàng)建一個副本,且在線程內(nèi)部任何地方都可以使用,線程之間互不影響,這樣一來就不存在線程安全問題,也不會嚴重影響程序執(zhí)行性能。
五、ThreadLocal工作原理
ThreadLocal
中的主要方法:
set方法
首先獲取到當前線程t,然后調(diào)用getMap
獲取ThreadLocalMap
,如果map存在,則將當前線程對象作為key,要存儲的對象作為value存到map中去,如果該map不存在,則初始化一個。
ThreadLocalMap
:
ThreadLocalMap
就是ThreadLocal
的一個靜態(tài)內(nèi)部類,里面定義了一個Entry
來保存數(shù)據(jù),而且還是繼承的弱引用。在Entry
內(nèi)部使用了ThreadLocal
作為key,使用我們設(shè)置的value作為value。
getMap
方法:
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
調(diào)用當前線程t,返回當前線程t中的成員變量threadLocals
,threadLocals
就是ThreadLocalMap
。
get()方法
首先獲取當前線程,然后調(diào)用getMap
方法獲取一個ThreadLocalMap
,如果map不為null,那就使用當前線程作為ThreadLocalMap
的Entry
的鍵,然后值就作為相應的值,如果沒有就設(shè)置一個初始值。
設(shè)置初始值:
remove()方法
從map
中移除即可。
六、小結(jié)
1.每個Thread內(nèi)部都維護著一個ThreadLocalMap
的引用
2.ThreadLocalMap是ThreadLocal
的內(nèi)部類,用Entry來進行存儲
3.ThreadLocal創(chuàng)建的副本是存儲在自己的threadLocals
中的,也就是自己的ThreadLocalMap
4.ThreadLocalMap的鍵值為ThreadLocal
對象,而且可以有多個threadLocals
變量,因此保存在map中。
5.在進行g(shù)et之前,必須先set,否則會報空指針異常,當然也可以初始化一個,但是必須重寫initialValue()
方法。
6.ThreadLocal本身并不存儲值,他只是作為一個key來讓線程從ThreadLocalMap
獲取value。
七、注意點
1.Thread中有一個map,就是ThreadLocalMap
2.ThreadLocalMap的key是ThreadLocal
,值是我們自己設(shè)定的。
3.ThreadLocal是一個弱引用,當為null時,會被當成垃圾回收。
4.如果我們ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此時我們的ThreadLocalMap生命周期和Thread的一樣,他不會回收,這時候就出現(xiàn)一個現(xiàn)象,就是ThreadLocalMap的key沒有了,但是value還在,這就造成了內(nèi)存泄漏。解決辦法:使用完ThreadLocal后,執(zhí)行remove操作,避免出現(xiàn)內(nèi)存溢出情況。
到此這篇關(guān)于Java并發(fā)編程之ThreadLocal詳解的文章就介紹到這了,更多相關(guān)Java ThreadLocal內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
教你從頭開始用JAVA創(chuàng)建一個自己的簡單API并實現(xiàn)第三方調(diào)用
在日常開發(fā)的時候,經(jīng)常會遇到需要調(diào)用別人的接口的場景,下面這篇文章主要給大家介紹了關(guān)于如何從頭開始用JAVA創(chuàng)建一個自己的簡單API并實現(xiàn)第三方調(diào)用的相關(guān)資料,需要的朋友可以參考下2023-12-12SpringBoot結(jié)合Mybatis實現(xiàn)創(chuàng)建數(shù)據(jù)庫表的方法
本文主要介紹了SpringBoot結(jié)合Mybatis實現(xiàn)創(chuàng)建數(shù)據(jù)庫表的方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01Spring?BeanPostProcessor后處理器源碼解析
這篇文章主要介紹了Spring?BeanPostProcessor后處理器源碼解析,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-09-09spring cloud oauth2 feign 遇到的坑及解決
這篇文章主要介紹了spring cloud oauth2 feign 遇到的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03java并發(fā)容器ConcurrentHashMap深入分析
這篇文章主要為大家介紹了java并發(fā)容器ConcurrentHashMap使用示例及深入分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05