Java執行緒(篇外篇):執行緒本地變數ThreadLocal
首先說明ThreadLocal存放的值是執行緒內共享的,執行緒間互斥的,主要用於執行緒內共享一些資料,避免通過引數來傳遞,這樣處理後,能夠優雅的解決一些實際問題,比如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()) {
- // 建立新的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) {
- // 異常處理
- }
- }
- }
這樣處理的好處:
- 統一管理Connection;
- 不需要顯示傳參Connection,程式碼更優雅;
- 降低耦合性。
ThreadLocal有四個方法,分別為:
initialValue
protected T initialValue()
- 返回此執行緒區域性變數的當前執行緒的初始值。最多在每次訪問執行緒來獲得每個執行緒區域性變數時呼叫此方法一次,即執行緒第一次使用
get()
方法訪問變數的時候。如果執行緒先於 get 方法呼叫set(T)
方法,則不會線上程中再呼叫 initialValue 方法。該實現只返回 null;如果程式設計師希望將執行緒區域性變數初始化為 null 以外的某個值,則必須為 ThreadLocal 建立子類,並重寫此方法。通常,將使用匿名內部類。initialValue 的典型實現將呼叫一個適當的構造方法,並返回新構造的物件。
-
- 返回:
- 返回此執行緒區域性變數的初始值
get
public T get()
- 返回此執行緒區域性變數的當前執行緒副本中的值。如果這是執行緒第一次呼叫該方法,則建立並初始化此副本。
-
- 返回:
- 此執行緒區域性變數的當前執行緒的值
set
public void set(T value)
- 將此執行緒區域性變數的當前執行緒副本中的值設定為指定值。許多應用程式不需要這項功能,它們只依賴於
initialValue()
方法來設定執行緒區域性變數的值。 -
- 引數:
value
- 儲存在此執行緒區域性變數的當前執行緒副本中的值。
remove
public void remove()
- 移除此執行緒區域性變數的值。這可能有助於減少執行緒區域性變數的儲存需求。如果再次訪問此執行緒區域性變數,那麼在預設情況下它將擁有其 initialValue。
很多人對ThreadLocal存在一定的誤解,說ThreadLocal中有一個全域性的Map,set時執行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
- // 建立一個當前執行緒本地變數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();
- }
(完)
本文來自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/15732053
相關文章
- 深入理解java:執行緒本地變數 java.lang.ThreadLocal類Java執行緒變數thread
- java 併發,為執行緒建立本地變數 ThreadLocal的使用Java執行緒變數thread
- Java執行緒(篇外篇):阻塞佇列BlockingQueueJava執行緒佇列BloC
- java多執行緒——ThreadLocalJava執行緒thread
- Java執行緒篇——執行緒的開啟Java執行緒
- Android執行緒篇(二)Java執行緒池Android執行緒Java
- Java多執行緒——執行緒Java執行緒
- 多執行緒(2)-執行緒同步條件變數執行緒變數
- Java多執行緒(一)多執行緒入門篇Java執行緒
- 《Java 高階篇》七:執行緒和執行緒池Java執行緒
- 執行緒本地ThreadLocal的介紹與使用!執行緒thread
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- Java多執行緒-執行緒中止Java執行緒
- Java多執行緒——執行緒池Java執行緒
- Java執行緒:執行緒中斷Java執行緒
- java 最大執行緒數Java執行緒
- 【多執行緒】ThreadLocal原理執行緒thread
- C#執行緒本地儲存:LocalDataStoreSlot和ThreadLocalC#執行緒LDAASTthread
- 程式執行緒篇——執行緒切換(下)執行緒
- 程式執行緒篇——執行緒切換(上)執行緒
- 程式執行緒篇——程式執行緒基礎執行緒
- java 多執行緒守護執行緒Java執行緒
- Java多執行緒-執行緒通訊Java執行緒
- Java多執行緒-執行緒狀態Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- java多執行緒9:執行緒池Java執行緒
- Java多執行緒之執行緒中止Java執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- java執行緒執行緒休眠,sleep方法Java執行緒
- Java多執行緒——守護執行緒Java執行緒
- Java多執行緒16:執行緒組Java執行緒
- Java多執行緒18:執行緒池Java執行緒
- 使用執行緒本地變數儲存會員資訊執行緒變數
- Java執行緒中斷與終止執行緒執行Java執行緒
- java執行緒之守護執行緒和使用者執行緒Java執行緒
- 多執行緒併發篇——如何停止執行緒執行緒
- java執行緒Java執行緒
- Android執行緒篇(四)深入理解Java執行緒池(二)Android執行緒Java