最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程中的線程本地變量ThreadLocal詳解

 更新時(shí)間:2023年11月18日 10:08:06   作者:尋道的 Programmer  
這篇文章主要介紹了Java線程中的線程本地變量ThreadLocal詳解,ThreadLocal存放的值是線程內(nèi)共享的,線程間互斥的,主要用于線程內(nèi)共享一些數(shù)據(jù),避免通過(guò)參數(shù)來(lái)傳遞,這樣處理后,能夠優(yōu)雅的解決一些實(shí)際問(wèn)題,需要的朋友可以參考下

ThreadLocal

首先說(shuō)明ThreadLocal存放的值是線程內(nèi)共享的,線程間互斥的,主要用于線程內(nèi)共享一些數(shù)據(jù),避免通過(guò)參數(shù)來(lái)傳遞,這樣處理后,能夠優(yōu)雅的解決一些實(shí)際問(wèn)題,比如Hibernate中的OpenSessionInView,就是使用ThreadLocal保存Session對(duì)象,還有我們經(jīng)常用ThreadLocal存放Connection,代碼如:

/**
 * 數(shù)據(jù)庫(kù)連接管理類
 * @author 爽
 *
 */
public class ConnectionManager {
 
	/** 線程內(nèi)共享Connection,ThreadLocal通常是全局的,支持泛型 */
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
	
	public static Connection getCurrConnection() {
		// 獲取當(dāng)前線程內(nèi)共享的Connection
		Connection conn = threadLocal.get();
		try {
			// 判斷連接是否可用
			if(conn == null || conn.isClosed()) {
				// 創(chuàng)建新的Connection賦值給conn(略)
				// 保存Connection
				threadLocal.set(conn);
			}
		} catch (SQLException e) {
			// 異常處理
		}
		return conn;
	}
	
	/**
	 * 關(guān)閉當(dāng)前數(shù)據(jù)庫(kù)連接
	 */
	public static void close() {
		// 獲取當(dāng)前線程內(nèi)共享的Connection
		Connection conn = threadLocal.get();
		try {
			// 判斷是否已經(jīng)關(guān)閉
			if(conn != null && !conn.isClosed()) {
				// 關(guān)閉資源
				conn.close();
				// 移除Connection
				threadLocal.remove();
				conn = null;
			}
		} catch (SQLException e) {
			// 異常處理
		}
	}
}

這樣處理的好處:

  • 統(tǒng)一管理Connection;
  • 不需要顯示傳參Connection,代碼更優(yōu)雅;
  • 降低耦合性。

ThreadLocal有四個(gè)方法

initialValue

protected T initialValue()

返回此線程局部變量的當(dāng)前線程的初始值。最多在每次訪問(wèn)線程來(lái)獲得每個(gè)線程局部變量時(shí)調(diào)用此方法一次,即線程第一次使用 get() 方法訪問(wèn)變量的時(shí)候。如果線程先于 get 方法調(diào)用 set(T) 方法,則不會(huì)在線程中再調(diào)用 initialValue 方法。

該實(shí)現(xiàn)只返回 null;如果程序員希望將線程局部變量初始化為 null 以外的某個(gè)值,則必須為 ThreadLocal 創(chuàng)建子類,并重寫(xiě)此方法。通常,將使用匿名內(nèi)部類。initialValue 的典型實(shí)現(xiàn)將調(diào)用一個(gè)適當(dāng)?shù)臉?gòu)造方法,并返回新構(gòu)造的對(duì)象。

返回:

返回此線程局部變量的初始值

get

public T get()

返回此線程局部變量的當(dāng)前線程副本中的值。如果這是線程第一次調(diào)用該方法,則創(chuàng)建并初始化此副本。

返回:

此線程局部變量的當(dāng)前線程的值

set

public void set(T value)

將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為指定值。許多應(yīng)用程序不需要這項(xiàng)功能,它們只依賴于 initialValue() 方法來(lái)設(shè)置線程局部變量的值。

參數(shù):

value - 存儲(chǔ)在此線程局部變量的當(dāng)前線程副本中的值。

remove

public void remove()

移除此線程局部變量的值。這可能有助于減少線程局部變量的存儲(chǔ)需求。如果再次訪問(wèn)此線程局部變量,那么在默認(rèn)情況下它將擁有其 initialValue。

很多人對(duì)ThreadLocal存在一定的誤解,說(shuō)ThreadLocal中有一個(gè)全局的Map,set時(shí)執(zhí)行map.put(Thread.currentThread(), value),get和remove時(shí)也同理,但SUN的大師們是否是如此實(shí)現(xiàn)的,我們只能去看源碼了。

源碼解讀

set方法

/**
 * Sets the current thread's copy of this thread-local variable
 * to the specified value.  Most subclasses will have no need to
 * override this method, relying solely on the {@link #initialValue}
 * method to set the values of thread-locals.
 *
 * @param value the value to be stored in the current thread's copy of
 *        this thread-local.
 */
public void set(T value) {
	// 獲取當(dāng)前線程對(duì)象
	Thread t = Thread.currentThread();
	// 獲取當(dāng)前線程本地變量Map
	ThreadLocalMap map = getMap(t);
	// map不為空
	if (map != null)
		// 存值
		map.set(this, value);
	else
		// 創(chuàng)建一個(gè)當(dāng)前線程本地變量Map
		createMap(t, value);
}
 
/**
 * Get the map associated with a ThreadLocal. Overridden in
 * InheritableThreadLocal.
 *
 * @param  t the current thread
 * @return the map
 */
ThreadLocalMap getMap(Thread t) {
	// 獲取當(dāng)前線程的本地變量Map
	return t.threadLocals;
}

這里注意,ThreadLocal中是有一個(gè)Map,但這個(gè)Map不是我們平時(shí)使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個(gè)內(nèi)部類,不對(duì)外使用的。當(dāng)使用ThreadLocal存值時(shí),首先是獲取到當(dāng)前線程對(duì)象,然后獲取到當(dāng)前線程本地變量Map,最后將當(dāng)前使用的ThreadLocal和傳入的值放到Map中,也就是說(shuō)ThreadLocalMap中存的值是[ThreadLocal對(duì)象, 存放的值],這樣做的好處是,每個(gè)線程都對(duì)應(yīng)一個(gè)本地變量的Map,所以一個(gè)線程可以存在多個(gè)線程本地變量。

get方法

/**
 * Returns the value in the current thread's copy of this
 * thread-local variable.  If the variable has no value for the
 * current thread, it is first initialized to the value returned
 * by an invocation of the {@link #initialValue} method.
 *
 * @return the current thread's value of this thread-local
 */
public T get() {
	Thread t = Thread.currentThread();
	ThreadLocalMap map = getMap(t);
	if (map != null) {
		ThreadLocalMap.Entry e = map.getEntry(this);
		if (e != null)
			return (T)e.value;
	}
	// 如果值為空,則返回初始值
	return setInitialValue();
}

有了之前set方法的分析,get方法也同理,需要說(shuō)明的是,如果沒(méi)有進(jìn)行過(guò)set操作,那從ThreadLocalMap中拿到的值就是null,這時(shí)get方法會(huì)返回初始值,也就是調(diào)用initialValue()方法,ThreadLocal中這個(gè)方法默認(rèn)返回null。當(dāng)我們有需要第一次get時(shí)就能得到一個(gè)值時(shí),可以繼承ThreadLocal,并且覆蓋initialValue()方法。

到此這篇關(guān)于Java線程中的線程本地變量ThreadLocal詳解的文章就介紹到這了,更多相關(guān)Java線程本地變量ThreadLocal內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 雙token實(shí)現(xiàn)token超時(shí)策略示例

    雙token實(shí)現(xiàn)token超時(shí)策略示例

    用于restful的app應(yīng)用無(wú)狀態(tài)無(wú)sesion登錄示例,需要的朋友可以參考下
    2014-02-02
  • Java中初始化List集合的6種方式詳解

    Java中初始化List集合的6種方式詳解

    這篇文章主要介紹了Java中初始化List集合的6種方式詳解,List 是 Java 開(kāi)發(fā)中經(jīng)常會(huì)使用的集合,在使用List時(shí)需要進(jìn)行初始化操作,今天我們就來(lái)看一下常用的幾種list集合初始化方式,需要的朋友可以參考下
    2023-10-10
  • Spring實(shí)現(xiàn)處理跨域請(qǐng)求代碼詳解

    Spring實(shí)現(xiàn)處理跨域請(qǐng)求代碼詳解

    這篇文章主要介紹了Spring實(shí)現(xiàn)處理跨域請(qǐng)求代碼詳解,具有一定借鑒價(jià)值,需要的朋友可以了解下。
    2017-12-12
  • 網(wǎng)關(guān)Spring Cloud Gateway HTTP超時(shí)配置問(wèn)題

    網(wǎng)關(guān)Spring Cloud Gateway HTTP超時(shí)配置問(wèn)題

    這篇文章主要介紹了網(wǎng)關(guān)Spring Cloud Gateway HTTP超時(shí)配置問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java自定義實(shí)現(xiàn)equals()方法過(guò)程解析

    Java自定義實(shí)現(xiàn)equals()方法過(guò)程解析

    這篇文章主要介紹了Java自定義實(shí)現(xiàn)equals()方法過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java結(jié)構(gòu)型設(shè)計(jì)模式中建造者模式示例詳解

    Java結(jié)構(gòu)型設(shè)計(jì)模式中建造者模式示例詳解

    建造者模式,是一種對(duì)象構(gòu)建模式 它可以將復(fù)雜對(duì)象的建造過(guò)程抽象出來(lái),使這個(gè)抽象過(guò)程的不同實(shí)現(xiàn)方法可以構(gòu)造出不同表現(xiàn)的對(duì)象。本文將通過(guò)示例講解建造者模式,需要的可以參考一下
    2022-09-09
  • Java中死鎖與活鎖的具體實(shí)現(xiàn)

    Java中死鎖與活鎖的具體實(shí)現(xiàn)

    鎖發(fā)生在不同的請(qǐng)求中,本文主要介紹了Java中死鎖與活鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • springboot配置允許跨域訪問(wèn)代碼實(shí)例

    springboot配置允許跨域訪問(wèn)代碼實(shí)例

    這篇文章主要介紹了springboot配置允許跨域訪問(wèn)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java反射之Java獲取方法信息實(shí)踐

    Java反射之Java獲取方法信息實(shí)踐

    本文介紹了通過(guò)Java反射機(jī)制獲取類的信息,包括類的名稱、成員方法和成員變量,具體實(shí)現(xiàn)方式包括通過(guò)`getClass()`獲取類類型,使用`Method`類獲取方法對(duì)象,使用`Field`類獲取成員變量信息,文章還提供了完整實(shí)例代碼
    2026-05-05
  • C++/java 繼承類的多態(tài)詳解及實(shí)例代碼

    C++/java 繼承類的多態(tài)詳解及實(shí)例代碼

    這篇文章主要介紹了C++/java 繼承類的多態(tài)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02

最新評(píng)論

青川县| 项城市| 潼关县| 南康市| 北宁市| 兴义市| 安国市| 若尔盖县| 泗水县| 五寨县| 潍坊市| 雅江县| 巍山| 凤凰县| 林芝县| 岫岩| 射洪县| 西宁市| 霍山县| 林州市| 河北区| 高碑店市| 冕宁县| 保山市| 西安市| 台中县| 连云港市| 紫金县| 洛川县| 昭通市| 内江市| 荆门市| 清流县| 扎鲁特旗| 定兴县| 宜兰市| 喀喇沁旗| 金坛市| 福海县| 涿州市| 子洲县|