欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

ThreadLocal

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

/**
 * 數(shù)據(jù)庫連接管理類
 * @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ù)庫連接
	 */
	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有四個方法

initialValue

protected T initialValue()

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

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

返回:

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

get

public T get()

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

返回:

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

set

public void set(T value)

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

參數(shù):

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

remove

public void remove()

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

很多人對ThreadLocal存在一定的誤解,說ThreadLocal中有一個全局的Map,set時執(zhí)行map.put(Thread.currentThread(), value),get和remove時也同理,但SUN的大師們是否是如此實現(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)前線程對象
	Thread t = Thread.currentThread();
	// 獲取當(dāng)前線程本地變量Map
	ThreadLocalMap map = getMap(t);
	// map不為空
	if (map != null)
		// 存值
		map.set(this, value);
	else
		// 創(chuàng)建一個當(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中是有一個Map,但這個Map不是我們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個內(nèi)部類,不對外使用的。當(dāng)使用ThreadLocal存值時,首先是獲取到當(dāng)前線程對象,然后獲取到當(dāng)前線程本地變量Map,最后將當(dāng)前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal對象, 存放的值],這樣做的好處是,每個線程都對應(yīng)一個本地變量的Map,所以一個線程可以存在多個線程本地變量。

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方法也同理,需要說明的是,如果沒有進行過set操作,那從ThreadLocalMap中拿到的值就是null,這時get方法會返回初始值,也就是調(diào)用initialValue()方法,ThreadLocal中這個方法默認返回null。當(dāng)我們有需要第一次get時就能得到一個值時,可以繼承ThreadLocal,并且覆蓋initialValue()方法。

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

相關(guān)文章

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

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

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

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

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

    Spring oxm入門實例

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

    SpringBoot條件注解之@ConditionalOnClass等注解的使用場景分析

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

    簡單剖析Java中動態(tài)線程池的擴容以及縮容操作

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

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

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

    關(guān)于idea-web.xml版本過低怎么生成新的(web.xml報錯)問題

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

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

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

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

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

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

    下面小編就為大家?guī)硪黄獪\談java中String StringBuffer StringBuilder的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06

最新評論