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

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

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

ThreadLocal

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

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

這樣處理的好處:

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

ThreadLocal有四個方法

initialValue

protected T initialValue()

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

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

返回:

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

get

public T get()

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

返回:

此線程局部變量的當前線程的值

set

public void set(T value)

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

參數:

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

remove

public void remove()

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

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

源碼解讀

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) {
	// 獲取當前線程對象
	Thread t = Thread.currentThread();
	// 獲取當前線程本地變量Map
	ThreadLocalMap map = getMap(t);
	// map不為空
	if (map != null)
		// 存值
		map.set(this, value);
	else
		// 創(chuà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) {
	// 獲取當前線程的本地變量Map
	return t.threadLocals;
}

這里注意,ThreadLocal中是有一個Map,但這個Map不是我們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個內部類,不對外使用的。當使用ThreadLocal存值時,首先是獲取到當前線程對象,然后獲取到當前線程本地變量Map,最后將當前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal對象, 存放的值],這樣做的好處是,每個線程都對應一個本地變量的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方法會返回初始值,也就是調用initialValue()方法,ThreadLocal中這個方法默認返回null。當我們有需要第一次get時就能得到一個值時,可以繼承ThreadLocal,并且覆蓋initialValue()方法。

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

相關文章

  • 雙token實現token超時策略示例

    雙token實現token超時策略示例

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

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

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

    Spring實現處理跨域請求代碼詳解

    這篇文章主要介紹了Spring實現處理跨域請求代碼詳解,具有一定借鑒價值,需要的朋友可以了解下。
    2017-12-12
  • 網關Spring Cloud Gateway HTTP超時配置問題

    網關Spring Cloud Gateway HTTP超時配置問題

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

    Java自定義實現equals()方法過程解析

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

    Java結構型設計模式中建造者模式示例詳解

    建造者模式,是一種對象構建模式 它可以將復雜對象的建造過程抽象出來,使這個抽象過程的不同實現方法可以構造出不同表現的對象。本文將通過示例講解建造者模式,需要的可以參考一下
    2022-09-09
  • Java中死鎖與活鎖的具體實現

    Java中死鎖與活鎖的具體實現

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

    springboot配置允許跨域訪問代碼實例

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

    Java反射之Java獲取方法信息實踐

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

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

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

最新評論

宾川县| 宜兰县| 平顶山市| 曲靖市| 册亨县| 乐都县| 齐齐哈尔市| 阳城县| 嘉义县| 丰镇市| 丰城市| 麟游县| 廊坊市| 孝昌县| 沙湾县| 芮城县| 唐山市| 大余县| 连城县| 常山县| 滨州市| 金湖县| 德清县| 平定县| 门源| 汽车| 龙川县| 上杭县| 巴彦淖尔市| 华蓥市| 永川市| 山西省| 周口市| 抚远县| 兴仁县| 柘城县| 麦盖提县| 高雄市| 舒兰市| 平湖市| 漳浦县|