ThreadLocal本地線程變量的理解


   一般的Web應用划分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過接口向上層開放功能調用。在一般情況下,從接收請求到返回響應所經過的所有程序調用都同屬於一個線程。
     也就是說,同一線程貫通N層,不同的線程可能由於參數等不同會對程序中的某些變量進行修改,但是又要防止修改后的值對其它線程產生影響,因為不同的線程可以同時運行滴,這就需要我們解決對某些線程共享的變量的訪問沖突問題。ThreadLocal本地線程變量就是一種解決方式,它通過將程序中不安全的變量封裝進ThreadLocal中,這相當於為每一個線程提供一個獨立的變量副本(其實是不同的對象),線程修改變量的值對其它線程來說沒影響了,因為其它線程有自己的一個副本信息。
 
 
代碼理解:
 1 // 借助ThreadLocal對象每個線程只創建一個實例
 2 public static final String dateFormat="yyyy-MM-dd";
 3 
 4 private static final ThreadLocal<DateFormat> dfThreadLocal=new ThreadLocal<DateFormat>(){
 5      @Override
 6      protected DateFormat initialValue() {
 7          return new SimpleDateFormat(dateFormat);
 8      }
 9 };
10 
11 public static String dateToString(Date date){
12      return dfThreadLocal.get().format(date);
13 }

 

  對於每個線程,都有一個類似於Map的東西ThreadLocalMap(ThreadLocal的靜態類 ),那它里面保存了什么東東呢,肯定是key-value啊,key就是上面代碼中的共享靜態變量 dfThreadLocal,value就是DateFormat實例了,即new SimpleDateFormat(dateFormat)這個東東。那接下來,在線程內我要如何去獲取這個值呢,就是靠dfThreadLocal.get()實現滴,方法源碼如下:
 1 ThreadLocal .ThreadLocalMap inheritableThreadLocals = null ;
 2  
 3 public T get () {
 4     Thread t = Thread.currentThread ();
 5     ThreadLocalMap map = getMap(t );
 6     if ( map != null) {
 7         ThreadLocalMap.Entry e = map.getEntry (this);
 8         if ( e != null)
 9             return ( T)e .value;
10     }
11     return setInitialValue ();
12 }
13 
14 ThreadLocalMap getMap (Thread t) {
15    return t .inheritableThreadLocals;
16 }
 
   可以很明顯的看出, 首先根據Thread.currentThread ()獲取到inheritableThreadLocals(即ThreadLocalMap,他是Thread的一個變量),然后將this(即最上面代碼的dfThreadLocal對象)作為key(或索引)獲取到真正的值T(就是SimpleDateFormat對象)啊,至此應該比較清楚了。
    為什么不同的線程有各自的值,因為 不同的線程--->不同的ThreadLocalMap對象(線程的變量)--->通過相同的key(如果有被static修飾)獲取到不同的value值
  備注:一般都被static修飾,因為可以避免在一個線程內可能發生的重復創建TSO(Thread Specific Object,即ThreadLocal所關聯的對象),被statis修飾了,同一線程key也肯定一樣,value也肯定只有一份了。
 一個ThreadLocal實例關聯當前線程的一個TSO對象,如果把ThreadLocal聲明為實例變量,那么每創建一個類實例就會導致一個TSO實例誕生,這肯定沒有這個必要滴。
 
更多文章請見我的個人博客http://www.acanblog.com


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM