原貼地址:http://www.cnblogs.com/zhengbin/p/5674638.htmlhtml
閱讀目錄測試
"該類提供了線程局部(thread-local)變量。這些變量不一樣於它們的普通對應物,由於訪問某個變量(經過其get或set方法)的每一個線程都有本身的局部變量,它獨立於變量的初始化副本。ThreadLocal實例一般是類中的private static字段,它們但願將狀態與某一個線程(例如,用戶ID或事物ID)相關聯。"this
防止任務在共享資源上產生衝突的第二種方式是根除對變量的共享。線程本地存儲是一種自動化機制,能夠爲使用變量的每一個不一樣的線程都建立不一樣的存儲。所以,若是你有5個線程都要使用變量x所表示的對象,那線程本地存儲就會生成5個用於x的不一樣的存儲塊。主要是,它們使得你能夠將狀態與線程關聯起來。線程
每一個線程都有一個獨立於其它線程的上下文來保存這個變量,一個線程的本地變量對其它線程是不可見的。設計
ThreadLocal能夠給一個初始值,而每一個線程都會得到這個初始化值的一個副本,這樣才能保證不一樣的線程都有一份拷貝。3d
ThreadLocal不是用於解決共享變量的問題的,不是爲了協調線程同步而存在,而是爲了方便每一個線程處理本身的狀態而引入的一個機制,就像《Thinking in Java》中描述的那樣:」它們使得你能夠將狀態與線程關聯起來。「理解這點對正確使用ThreadLocal相當重要。code
從輸出的結果能夠看出,五個線程處理本身的本地變量值。htm
而這個測試的結果,並無相同。這是由於實例爲對象,因此初始值爲一個對象的引用,那麼五個線程的副本就是這個對象的引用的副本,也就是說這些引用仍是指向同一個對象,因此就出現了這種狀況。對象
1 public void set(T value) { 2 Thread t = Thread.currentThread(); 3 ThreadLocalMap map = getMap(t); 4 5 if (map != null) 6 map.set(this, value); 7 //說明線程第一次使用線程本地變量(注意這裏的第一次含義) 8 else 9 createMap(t, value); 10 }
1 public T get() { 2 //獲取當前執行線程 3 Thread t = Thread.currentThread(); 4 //取得當前線程的ThreadLocalMap實例 5 ThreadLocalMap map = getMap(t); 6 //若是map不爲空,說明該線程已經有了一個ThreadLocalMap實例 7 if (map != null) { 8 //map中保存線程的全部的線程本地變量,咱們要去查找當前線程本地變量 9 ThreadLocalMap.Entry e = map.getEntry(this); 10 //若是當前線程本地變量存在這個map中,則返回其對應的值 11 if (e != null) 12 return (T)e.value; 13 } 14 //若是map不存在或者map中不存在當前線程本地變量,返回初始值 15 return setInitialValue(); 16 }
這裏注意,ThreadLocal中是有一個Map,但這個Map不是咱們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個內部類,不對外使用的。當使用ThreadLocal存值時,首先是獲取到當前線程對象,而後獲取到當前線程本地變量Map,最後將當前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal對象, 存放的值],這樣作的好處是,每一個線程都對應一個本地變量的Map,因此一個線程能夠存在多個線程本地變量。下面提供一個簡單的實現版本:blog