ThreadLocal簡單理解,threadlocal理解
在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