Java中的ThreadLocal功能演示示例
除了使用synchronized
同步符號外,Java中的ThreadLocal
是另一種實現(xiàn)線程安全的方法。在進行性能測試用例的編寫過程中,比較簡單的辦法就是直接使用synchronized
關(guān)鍵字,修飾對象、方法以及類。但是使用synchronized
同步,這可能會影響應(yīng)用程序的可伸縮性以及運行效率。但是如果要在多個線程之間共享對象又要保障線程安全,則除了synchronized
之外沒有特別適合測試的方法。
Java中的ThreadLocal
是實現(xiàn)線程安全的另一種方法,它不滿足同步要求,而是通過為每個線程提供Object的顯式副本來消除共享。由于不再共享對象,因此不需要同步,它可以提高應(yīng)用程序的可伸縮性和運行效率。
在本文中,會介紹有關(guān)ThreadLocal
的基礎(chǔ)知識點點,Demo中ThreadLocal
的簡單示例。
ThreadLocal簡介
很多人幾乎都沒有用過ThreadLocal
類,因為在測試中能用到的地方實在太少了,而且測試腳本的性能一般來講都會很高,遠超被測服務(wù)的處理能力,所以即使全部使用synchronized
也不會有任何問題。
但是ThreadLocal
有很多真正的使用場景,這就是為什么將其添加到標(biāo)準Java平臺庫中的原因。盡管知道現(xiàn)在多線程編程測試中對于ThreadLocal
應(yīng)用并不多,但是我會在后期多進行一些實踐,分享給各位。
以下是Java中ThreadLocal
類的一些眾所周知的用法:
ThreadLocal
非常適合實現(xiàn)每個線程單例類或每個線程上下文信息(例如事務(wù)ID)。- 可以將任何非線程對象包裝在
ThreadLocal
中,并且將其使用變?yōu)榫€程安全的。ThreadLocal
的經(jīng)典示例之一是共享SimpleDateFormat
。由于SimpleDateFormat
不是線程安全的,因此使用全局格式化程序可能無法正常工作,但是使用每個線程格式化程序當(dāng)然可以工作。 ThreadLocal
提供了另一種擴展Thread
的方法。如果要保留信息或?qū)⑿畔囊粋€方法調(diào)用傳遞到另一個方法,則可以使用ThreadLocal
進行傳遞。- 由于不需要修改任何方法,因此可以提供極大的靈活性。
沒有兩個線程可以看到彼此的ThreadLocal
變量。J2EE應(yīng)用程序服務(wù)器中有一個ThreadLocal
的真實示例,該服務(wù)器使用Java ThreadLocal
變量來跟蹤事務(wù)和安全上下文。
為了避免過多的創(chuàng)建和共享全局實例時的切換成本,將諸如數(shù)據(jù)庫連接之類的重對象作為ThreadLocal共享是很有意義的。
ThreadLocal演示Demo
package com.fun.ztest.java; import com.fun.frame.SourceCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; /** * ThreadLocal演示測試類 */ public class FunTester extends SourceCode { public static Logger logger = LoggerFactory.getLogger(FunTester.class); /** * 這個是重點,通過ThreadLocal類重建線程私有的對象 */ private static final ThreadLocal<Object> format = new ThreadLocal() { @Override protected Object initialValue() { Object funTester = new Object(); logger.info("初始化對象,線程: {} 對象: {}", Thread.currentThread().getName(), funTester.hashCode()); return funTester; } }; public static void main(String args[]) throws IOException, InterruptedException { for (int i = 0; i < 5; i++) { Thread t = new Thread(new Fun()); t.start(); } } /** * 獲取對象 * * @return */ public static Object get() { return format.get(); } static class Fun implements Runnable { @Override public void run() { logger.info("線程: {} 對象: {}", Thread.currentThread().getName(), FunTester.get().hashCode()); } } }
控制臺輸出
INFO-> 當(dāng)前用戶:fv,IP:10.60.193.37,工作目錄:/Users/fv/Documents/workspace/fun/,系統(tǒng)編碼格式:UTF-8,系統(tǒng)Mac OS X版本:10.16 INFO-> 初始化對象,線程: Thread-1 對象: 347384150 INFO-> 初始化對象,線程: Thread-2 對象: 142607688 INFO-> 線程: Thread-1 對象: 347384150 INFO-> 線程: Thread-2 對象: 142607688 INFO-> 初始化對象,線程: Thread-3 對象: 1008357237 INFO-> 初始化對象,線程: Thread-4 對象: 559951532 INFO-> 線程: Thread-3 對象: 1008357237 INFO-> 線程: Thread-4 對象: 559951532 INFO-> 初始化對象,線程: Thread-5 對象: 748958847 INFO-> 線程: Thread-5 對象: 748958847 Process finished with exit code 0
如果查看上述程序的輸出,則會發(fā)現(xiàn),當(dāng)不同的線程調(diào)用ThreadLocal
類的get()
方法而不是調(diào)用其initialValue()
方法時,該方法將為該線程創(chuàng)建Object
的互斥實例對象。 由于Object
在線程之間不共享,并且實質(zhì)上在創(chuàng)建它自己的線程安全對象或者方法的線程本地是完全線程安全的。
ThreadLocal類知識點
- Java的ThreadLocal在JDK 1.2上引入,但后來在JDK 1.4中進行了泛化,以在ThreadLocal變量上引入類型安全性。
- ThreadLocal通常與Thread一起使用,由Thread執(zhí)行的所有代碼都可以訪問ThreadLocal變量,但是兩個線程看不到彼此的ThreadLocal變量。
- 每個線程都擁有ThreadLocal變量的互斥副本,該副本在線程完成或死亡(正常情況下或由于任何異常)后才有進行垃圾回收,因為這些ThreadLocal變量沒有任何其他線程引用。
- Java中的ThreadLocal變量通常是類中的私有靜態(tài)字段,并在Thread中維護其狀態(tài)。
不要誤解ThreadLocal是Synchronization的替代方法,它全部取決于你自己的程序設(shè)計。如果設(shè)計允許每個線程擁有自己的對象副本,則可以使用ThreadLocal。
項目中使用
這里一個處理requestid的類,通過ThreadLocal使用,可以保證每個請求都擁有唯一的一個追蹤標(biāo)記。
public class TraceKeyHolder { private static ThreadLocal<String> threadLocal = new ThreadLocal(); public TraceKeyHolder() { } public static String getTraceKey() { return (String)threadLocal.get(); } public static void setTraceKey(String traceKey) { threadLocal.set(traceKey); } public static void clear() { threadLocal.remove(); } }
以上就是Java中的ThreadLocal功能演示示例的詳細內(nèi)容,更多關(guān)于Java ThreadLocal功能的資料請關(guān)注腳本之家其它相關(guān)文章!
- Java ThreadLocal有什么作用你知道嗎
- Java ThreadLocal原理解析以及應(yīng)用場景分析案例詳解
- java并發(fā)編程之ThreadLocal詳解
- java中ThreadLocal的基本原理
- 面試官:java ThreadLocal真的會造成內(nèi)存泄露嗎
- 詳解Java中的ThreadLocal
- Java中ThreadLocal的一些理解
- java中ThreadLocal取不到值的兩種原因
- Java單線程ThreadLocal串值問題解決方案
- java中ThreadLocalRandom的使用詳解
- JAVA開發(fā)常用類庫UUID、Optional、ThreadLocal、TimerTask、Base64使用方法與實例詳解
- Java中的ThreadLocal詳解
相關(guān)文章
方法參數(shù)屬性params,@PathVariable和@RequestParam用法及區(qū)別
這篇文章主要介紹了方法參數(shù)屬性params,@PathVariable和@RequestParam用法及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10eclipse連接數(shù)據(jù)庫并實現(xiàn)用戶注冊登錄功能
這篇文章主要介紹了eclipse連接數(shù)據(jù)庫并實現(xiàn)用戶注冊登錄功能的相關(guān)資料,需要的朋友可以參考下2021-01-01如何在mybatis中向BLOB字段批量插入數(shù)據(jù)
這篇文章主要介紹了如何在mybatis中向BLOB字段批量插入數(shù)據(jù)的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-10-10slf4j與jul、log4j1、log4j2、logback的集成原理
這篇文章主要介紹了slf4j與jul、log4j1、log4j2、logback的集成原理,以及通用日志框架與具體日志實現(xiàn)系統(tǒng)的機制機制介紹,包括依賴的jar包,jar沖突處理等2022-03-03