close
文章出處
文章列表
在java開源項目的代碼中看到一個類里ThreadLocal的屬性:
private static ThreadLocal<Boolean> clientMode = new ThreadLocal<>();
印象中在看書的時候見到過ThreadLocal,但突然就想不起它的用處了。。心里一驚感覺當時書白看了。于是馬上網上查了查。
原來它的意思是線程的本地變量,ThreadLocal更像是一個線程變量訪問的工具類。
那為什么要用這種方法呢?
翻看了《Java并發編程實踐》,看到這么一個說法:線程本地變量通常用于防止可變單例或者全局變量的設計中,出現不正確的共享。
感覺這個看著很生硬啊。書中也舉了例子,是JDBC的Connection的應用。Connection對于單線程的程序中,一般會啟動時就創建好,這樣就不用每次都創建對象啦。但是換到多線程環境下就不行了,因為JDBC規范并沒有要求Connection是線程安全的。那么如果要解決就可以使用ThreadLocal。使用ThreadLocal可以在每個線程中創建一個Connection對象,這樣就滿足線程安全要求了。
這里比較好奇的是ThreadLocal是如何做到這些的呢?
ThreadLocal的實現
打開源代碼,ThreadLocal是個泛型類,里面也并不復雜,看到的構造函數也是什么也沒有做。ThreadLocal中比較常用的方法主要是set和get。最主要的奧秘便是下面這幾行代碼:
private final int threadLocalHashCode = nextHashCode(); /** * The next hash code to be given out. Updated atomically. Starts at * zero. */ private static AtomicInteger nextHashCode = new AtomicInteger(); /** * The difference between successively generated hash codes - turns * implicit sequential thread-local IDs into near-optimally spread * multiplicative hash values for power-of-two-sized tables. */ private static final int HASH_INCREMENT = 0x61c88647; /** * Returns the next hash code. */ private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); }
threadLocalHashCode這個變量會隨著ThreadLocal構造時創建,而初始化它的是一個nextHashCode()方法。從nextHashCode方法便知道是對一個整形變量nextHashCode進行了一個加法運算,而是固定的增加HASH_INCREMENT大小。
這樣做是什么意思呢?其實就是每次創建ThreadLocal時都產生一次新的hash值,就是讓每次的對象不一樣。那么有何用處?
再看看set方法,因為這個方法是ThreadLocal將變量設置到線程中的方法:
/** * 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(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
可以看到方法的執行過程:
1、獲得當前線程的實例
2、然后從線程里獲取ThreadLocalMap對象,這就是線程里存本地變量的地方
3、如果map不為空則將value寫入到map中,而key就是當前ThreadLocal的對象
4、如果為null,剛創建map,當然同樣會將value寫入map中,key同樣是ThreadLocal的對象
這樣就理解了,其實ThreadLocal每次產生一個新的對象,以此來保證每個線程都針對一個ThreadLocal對象。然后將數據通過set方法向線程中的threadLocals寫入值,以此來保證線程安全。當然在寫入的value必須不是一個共享對象,否則也是無法保證一定線程安全的。
引用:
《java并發編程實踐》
正確理解ThreadLocal:http://www.iteye.com/topic/103804
注:此文章為原創,歡迎轉載,請在文章頁面明顯位置給出此文鏈接!
若您覺得這篇文章還不錯請點擊下右下角的推薦,非常感謝!
http://www.cnblogs.com/5207
文章列表
![]() |
不含病毒。www.avast.com |
全站熱搜