Java中的ThreadLocal功能演示示例
除了使用synchronized同步符號(hào)外,Java中的ThreadLocal是另一種實(shí)現(xiàn)線(xiàn)程安全的方法。在進(jìn)行性能測(cè)試用例的編寫(xiě)過(guò)程中,比較簡(jiǎn)單的辦法就是直接使用synchronized關(guān)鍵字,修飾對(duì)象、方法以及類(lèi)。但是使用synchronized同步,這可能會(huì)影響應(yīng)用程序的可伸縮性以及運(yùn)行效率。但是如果要在多個(gè)線(xiàn)程之間共享對(duì)象又要保障線(xiàn)程安全,則除了synchronized之外沒(méi)有特別適合測(cè)試的方法。
Java中的ThreadLocal是實(shí)現(xiàn)線(xiàn)程安全的另一種方法,它不滿(mǎn)足同步要求,而是通過(guò)為每個(gè)線(xiàn)程提供Object的顯式副本來(lái)消除共享。由于不再共享對(duì)象,因此不需要同步,它可以提高應(yīng)用程序的可伸縮性和運(yùn)行效率。
在本文中,會(huì)介紹有關(guān)ThreadLocal的基礎(chǔ)知識(shí)點(diǎn)點(diǎn),Demo中ThreadLocal的簡(jiǎn)單示例。
ThreadLocal簡(jiǎn)介
很多人幾乎都沒(méi)有用過(guò)ThreadLocal類(lèi),因?yàn)樵跍y(cè)試中能用到的地方實(shí)在太少了,而且測(cè)試腳本的性能一般來(lái)講都會(huì)很高,遠(yuǎn)超被測(cè)服務(wù)的處理能力,所以即使全部使用synchronized也不會(huì)有任何問(wèn)題。
但是ThreadLocal有很多真正的使用場(chǎng)景,這就是為什么將其添加到標(biāo)準(zhǔn)Java平臺(tái)庫(kù)中的原因。盡管知道現(xiàn)在多線(xiàn)程編程測(cè)試中對(duì)于ThreadLocal應(yīng)用并不多,但是我會(huì)在后期多進(jìn)行一些實(shí)踐,分享給各位。
以下是Java中ThreadLocal類(lèi)的一些眾所周知的用法:
ThreadLocal非常適合實(shí)現(xiàn)每個(gè)線(xiàn)程單例類(lèi)或每個(gè)線(xiàn)程上下文信息(例如事務(wù)ID)。- 可以將任何非線(xiàn)程對(duì)象包裝在
ThreadLocal中,并且將其使用變?yōu)榫€(xiàn)程安全的。ThreadLocal的經(jīng)典示例之一是共享SimpleDateFormat。由于SimpleDateFormat不是線(xiàn)程安全的,因此使用全局格式化程序可能無(wú)法正常工作,但是使用每個(gè)線(xiàn)程格式化程序當(dāng)然可以工作。 ThreadLocal提供了另一種擴(kuò)展Thread的方法。如果要保留信息或?qū)⑿畔囊粋€(gè)方法調(diào)用傳遞到另一個(gè)方法,則可以使用ThreadLocal進(jìn)行傳遞。- 由于不需要修改任何方法,因此可以提供極大的靈活性。
沒(méi)有兩個(gè)線(xiàn)程可以看到彼此的ThreadLocal變量。J2EE應(yīng)用程序服務(wù)器中有一個(gè)ThreadLocal的真實(shí)示例,該服務(wù)器使用Java ThreadLocal變量來(lái)跟蹤事務(wù)和安全上下文。
為了避免過(guò)多的創(chuàng)建和共享全局實(shí)例時(shí)的切換成本,將諸如數(shù)據(jù)庫(kù)連接之類(lèi)的重對(duì)象作為T(mén)hreadLocal共享是很有意義的。
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演示測(cè)試類(lèi)
*/
public class FunTester extends SourceCode {
public static Logger logger = LoggerFactory.getLogger(FunTester.class);
/**
* 這個(gè)是重點(diǎn),通過(guò)ThreadLocal類(lèi)重建線(xiàn)程私有的對(duì)象
*/
private static final ThreadLocal<Object> format = new ThreadLocal() {
@Override
protected Object initialValue() {
Object funTester = new Object();
logger.info("初始化對(duì)象,線(xiàn)程: {} 對(duì)象: {}", 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();
}
}
/**
* 獲取對(duì)象
*
* @return
*/
public static Object get() {
return format.get();
}
static class Fun implements Runnable {
@Override
public void run() {
logger.info("線(xiàn)程: {} 對(duì)象: {}", Thread.currentThread().getName(), FunTester.get().hashCode());
}
}
}
控制臺(tái)輸出
INFO-> 當(dāng)前用戶(hù):fv,IP:10.60.193.37,工作目錄:/Users/fv/Documents/workspace/fun/,系統(tǒng)編碼格式:UTF-8,系統(tǒng)Mac OS X版本:10.16 INFO-> 初始化對(duì)象,線(xiàn)程: Thread-1 對(duì)象: 347384150 INFO-> 初始化對(duì)象,線(xiàn)程: Thread-2 對(duì)象: 142607688 INFO-> 線(xiàn)程: Thread-1 對(duì)象: 347384150 INFO-> 線(xiàn)程: Thread-2 對(duì)象: 142607688 INFO-> 初始化對(duì)象,線(xiàn)程: Thread-3 對(duì)象: 1008357237 INFO-> 初始化對(duì)象,線(xiàn)程: Thread-4 對(duì)象: 559951532 INFO-> 線(xiàn)程: Thread-3 對(duì)象: 1008357237 INFO-> 線(xiàn)程: Thread-4 對(duì)象: 559951532 INFO-> 初始化對(duì)象,線(xiàn)程: Thread-5 對(duì)象: 748958847 INFO-> 線(xiàn)程: Thread-5 對(duì)象: 748958847 Process finished with exit code 0
如果查看上述程序的輸出,則會(huì)發(fā)現(xiàn),當(dāng)不同的線(xiàn)程調(diào)用ThreadLocal類(lèi)的get()方法而不是調(diào)用其initialValue()方法時(shí),該方法將為該線(xiàn)程創(chuàng)建Object的互斥實(shí)例對(duì)象。 由于Object在線(xiàn)程之間不共享,并且實(shí)質(zhì)上在創(chuàng)建它自己的線(xiàn)程安全對(duì)象或者方法的線(xiàn)程本地是完全線(xiàn)程安全的。
ThreadLocal類(lèi)知識(shí)點(diǎn)
- Java的ThreadLocal在JDK 1.2上引入,但后來(lái)在JDK 1.4中進(jìn)行了泛化,以在ThreadLocal變量上引入類(lèi)型安全性。
- ThreadLocal通常與Thread一起使用,由Thread執(zhí)行的所有代碼都可以訪(fǎng)問(wèn)ThreadLocal變量,但是兩個(gè)線(xiàn)程看不到彼此的ThreadLocal變量。
- 每個(gè)線(xiàn)程都擁有ThreadLocal變量的互斥副本,該副本在線(xiàn)程完成或死亡(正常情況下或由于任何異常)后才有進(jìn)行垃圾回收,因?yàn)檫@些ThreadLocal變量沒(méi)有任何其他線(xiàn)程引用。
- Java中的ThreadLocal變量通常是類(lèi)中的私有靜態(tài)字段,并在Thread中維護(hù)其狀態(tài)。
不要誤解ThreadLocal是Synchronization的替代方法,它全部取決于你自己的程序設(shè)計(jì)。如果設(shè)計(jì)允許每個(gè)線(xiàn)程擁有自己的對(duì)象副本,則可以使用ThreadLocal。
項(xiàng)目中使用
這里一個(gè)處理requestid的類(lèi),通過(guò)ThreadLocal使用,可以保證每個(gè)請(qǐng)求都擁有唯一的一個(gè)追蹤標(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功能演示示例的詳細(xì)內(nèi)容,更多關(guān)于Java ThreadLocal功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Java ThreadLocal有什么作用你知道嗎
- Java ThreadLocal原理解析以及應(yīng)用場(chǎng)景分析案例詳解
- java并發(fā)編程之ThreadLocal詳解
- java中ThreadLocal的基本原理
- 面試官:java ThreadLocal真的會(huì)造成內(nèi)存泄露嗎
- 詳解Java中的ThreadLocal
- Java中ThreadLocal的一些理解
- java中ThreadLocal取不到值的兩種原因
- Java單線(xiàn)程ThreadLocal串值問(wèn)題解決方案
- java中ThreadLocalRandom的使用詳解
- JAVA開(kāi)發(fā)常用類(lèi)庫(kù)UUID、Optional、ThreadLocal、TimerTask、Base64使用方法與實(shí)例詳解
- Java中的ThreadLocal詳解
相關(guān)文章
Java web過(guò)濾器驗(yàn)證登錄防止未登錄進(jìn)入界面
這篇文章主要介紹了Java web過(guò)濾器驗(yàn)證登錄防止未登錄進(jìn)入界面,在一些系統(tǒng)中經(jīng)??梢杂玫酱斯δ埽瑢?duì)java web 驗(yàn)證登錄知識(shí)感興趣的朋友一起看下吧2016-08-08
Rabbitmq延遲隊(duì)列實(shí)現(xiàn)定時(shí)任務(wù)的方法
這篇文章主要介紹了Rabbitmq延遲隊(duì)列實(shí)現(xiàn)定時(shí)任務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Java虛擬機(jī)常見(jiàn)內(nèi)存溢出錯(cuò)誤匯總
這篇文章主要匯總了Java虛擬機(jī)常見(jiàn)的內(nèi)存溢出錯(cuò)誤,警示大家,避免出錯(cuò),感興趣的朋友可以了解下2020-09-09
阿里通用OCR文字識(shí)別/圖像識(shí)別/圖片識(shí)別對(duì)接代碼示例(Java篇)
這篇文章主要介紹了阿里通用OCR文字識(shí)別/圖像識(shí)別/圖片識(shí)別對(duì)接(Java篇)的相關(guān)資料,文中詳細(xì)介紹了包括開(kāi)通服務(wù)、測(cè)試圖片、編寫(xiě)識(shí)別代碼、處理識(shí)別結(jié)果等步驟,需要的朋友可以參考下2024-12-12
Spring AOP實(shí)現(xiàn)Redis緩存數(shù)據(jù)庫(kù)查詢(xún)?cè)创a
這篇文章主要介紹了Spring AOP實(shí)現(xiàn)Redis緩存數(shù)據(jù)庫(kù)查詢(xún)的相關(guān)內(nèi)容,源碼部分還是不錯(cuò)的,需要的朋友可以參考下。2017-09-09
SpringBoot啟動(dòng)時(shí)自動(dòng)執(zhí)行sql腳本的方法步驟
本文主要介紹了SpringBoot啟動(dòng)時(shí)自動(dòng)執(zhí)行sql腳本的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09

