亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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)建子類,并重寫此方法。通常,將使用匿名內(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)文章

  • java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì)

    java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì)

    本篇文章java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì),可以實(shí)現(xiàn)商品的關(guān)聯(lián)統(tǒng)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • 2020JDK1.8安裝教程詳解(一次就可安裝成功)

    2020JDK1.8安裝教程詳解(一次就可安裝成功)

    這篇文章主要介紹了2020JDK1.8安裝教程詳解(一次就可安裝成功),本文通過(guò)圖文并茂的形式分步驟給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-08-08
  • Spring oxm入門實(shí)例

    Spring oxm入門實(shí)例

    這篇文章主要介紹了Spring oxm入門實(shí)例,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • SpringBoot條件注解之@ConditionalOnClass等注解的使用場(chǎng)景分析

    SpringBoot條件注解之@ConditionalOnClass等注解的使用場(chǎng)景分析

    文章詳細(xì)介紹了SpringBoot中條件注解的體系,包括基本概念、@ConditionalOnClass等常用注解的工作原理和使用場(chǎng)景,文章還探討了條件注解的組合使用、實(shí)戰(zhàn)應(yīng)用以及最佳實(shí)踐,幫助開(kāi)發(fā)者更好地理解和應(yīng)用條件注解,實(shí)現(xiàn)更靈活和智能的應(yīng)用配置,感興趣的朋友一起看看吧
    2025-03-03
  • 簡(jiǎn)單剖析Java中動(dòng)態(tài)線程池的擴(kuò)容以及縮容操作

    簡(jiǎn)單剖析Java中動(dòng)態(tài)線程池的擴(kuò)容以及縮容操作

    這篇文章主要為大家詳細(xì)介紹了Java中動(dòng)態(tài)線程池的擴(kuò)容以及縮容操作的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • Java對(duì)象創(chuàng)建內(nèi)存案例解析

    Java對(duì)象創(chuàng)建內(nèi)存案例解析

    這篇文章主要介紹了Java對(duì)象創(chuàng)建內(nèi)存案例解析,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 關(guān)于idea-web.xml版本過(guò)低怎么生成新的(web.xml報(bào)錯(cuò))問(wèn)題

    關(guān)于idea-web.xml版本過(guò)低怎么生成新的(web.xml報(bào)錯(cuò))問(wèn)題

    今天通過(guò)本文給大家分享idea-web.xml版本過(guò)低怎么生成新的(web.xml報(bào)錯(cuò))問(wèn)題,通過(guò)更換web.xml版本解決此問(wèn)題,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • kafka springBoot配置的實(shí)現(xiàn)

    kafka springBoot配置的實(shí)現(xiàn)

    本文主要介紹了kafka springBoot配置的實(shí)現(xiàn),通過(guò)詳細(xì)解析Spring Boot for Apache Kafka的配置選項(xiàng),以及如何優(yōu)化Kafka生產(chǎn)者和消費(fèi)者的屬性設(shè)置,感興趣的可以了解一下
    2023-11-11
  • 史上最通俗理解的Java死鎖代碼演示

    史上最通俗理解的Java死鎖代碼演示

    這篇文章主要給大家介紹了關(guān)于Java死鎖代碼演示的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 淺談java中String StringBuffer StringBuilder的區(qū)別

    淺談java中String StringBuffer StringBuilder的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談java中String StringBuffer StringBuilder的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06

最新評(píng)論