<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    理解java中的ThreadLocal


     

    一、對ThreadLocal概術

               


    JDK API 寫道:

    該類提供了線程局部 (thread-local) 變量。這些變量不同于它們的普通對應物,因為訪問某個變量(通過其 get 或 set 方法)的每個線程都有自己的局部變量,它獨立于變量的初始化副本。ThreadLocal 實例通常是類中的 private static 字段,它們希望將狀態(tài)與某一個線程(例如,用戶 ID 或事務 ID)相關聯(lián)。




    二、結合源碼理解



    可以看到ThreadLocal類中的變量只有這3int型:


        
    private final int threadLocalHashCode = nextHashCode();

      

        
    private static AtomicInteger nextHashCode = new AtomicInteger();

      

        
    private static final int HASH_INCREMENT = 0x61c88647;


        ThreadLocal實例的變量只有 threadLocalHashCode 
        ThreadLocal類的靜態(tài)變量nextHashCode 和HASH_INCREMENT
        實際上HASH_INCREMENT是一個常量,表示了連續(xù)分配的兩個ThreadLocal實例的 threadLocalHashCode值的增量,而nextHashCode 的表示了即將分配的下一個ThreadLocal實例的threadLocalHashCode 的值。

       而nextHashCode()方法就是將ThreadLocal類的下一個hashCode值即nextHashCode的值賦給實例的threadLocalHashCode,然后nextHashCode的值增加HASH_INCREMENT這個值。   

        private static int nextHashCode() {
        
    return nextHashCode.getAndAdd(HASH_INCREMENT); 
        }



       ThreadLocal有一個ThreadLocalMap靜態(tài)內(nèi)部類,你可以簡單理解為一個MAP,這個‘Map’為每個線程復制一個變量的‘拷貝’存儲其中。

     看一下set()方法:  獲取當前線程的引用,從map中獲取該線程對應的map,如果map存在更新緩存值,否則創(chuàng)建并存儲
      


        
    public void set(T value) {
            Thread t 
    = Thread.currentThread();
            ThreadLocalMap map 
    = getMap(t);
            
    if (map != null)
                map.set(
    this, value);
            
    else
                createMap(t, value);
        }


     
     再來看一下get()方法: 首先獲取當前線程引用,以此為key去獲取響應的ThreadLocalMap,如果此‘Map’不存在則初始化一個,否則返回其中的變量。
      調(diào)用get方法如果此Map不存在首先初始化,創(chuàng)建此map,將線程為key,初始化的vlaue存入其中,注意此處的initialValue,我們可以覆蓋此方法,在首次調(diào)用時初始化一個適當?shù)闹担J是null

     
        
    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();
        }

     


        
    private T setInitialValue() {
            T value 
    = initialValue();
            Thread t 
    = Thread.currentThread();
            ThreadLocalMap map 
    = getMap(t);
            
    if (map != null)
                map.set(
    this, value);
            
    else
                createMap(t, value);
            
    return value;
        }

     


        
    protected T initialValue() {
            
    return null;
        }




    我們來看下ThreadLocalMap靜態(tài)內(nèi)部類,ThreadLocalMap 內(nèi)部的Entry WeakReference

    static class ThreadLocalMap {

          

            
    static class Entry extends WeakReference<ThreadLocal> {
                
    /** The value associated with this ThreadLocal. */
                Object value;

                Entry(ThreadLocal k, Object v) 
    {
                    
    super(k);
                    value 
    = v;
                }

            }

    。。。。。

     
    ThreadLocal和多線程并發(fā)沒有什么關系。ThreadLocal模式是為了解決單線程內(nèi)的跨類跨方法調(diào)用的
    ThreadLocal不是用來解決對象共享訪問問題的,而主要是提供了保持對象的方法和避免參數(shù)傳遞的方便的對象訪問方式。一般情況下,通過ThreadLocal.set() 到線程中的對象是該線程自己使用的對象,其他線程是不需要訪問的,也訪問不到的。各個線程中訪問的是不同的對象。





    三、例子




    引用Tim Cull的博文“SimpleDateFormat: Performance Pig”介紹下ThreadLocal的簡單使用,同時也對SimpleDateFormat的使用有個深入的了解。

     

    Tim Cull 寫道:

       Tim Cull碰到一個SimpleDateFormat帶來的嚴重的性能問題,該問題主要有SimpleDateFormat引發(fā),創(chuàng)建一個 SimpleDateFormat實例的開銷比較昂貴,解析字符串時間時頻繁創(chuàng)建生命周期短暫的實例導致性能低下。即使將 SimpleDateFormat定義為靜態(tài)類變量,貌似能解決這個問題,但是SimpleDateFormat是非線程安全的,同樣存在問題,如果用 ‘synchronized’線程同步同樣面臨問題,同步導致性能下降(線程之間序列化的獲取SimpleDateFormat實例)。

        Tim Cull使用Threadlocal解決了此問題,對于每個線程SimpleDateFormat不存在影響他們之間協(xié)作的狀態(tài),為每個線程創(chuàng)建一個SimpleDateFormat變量的拷貝或者叫做副本

    import java.text.DateFormat;  
    import java.text.ParseException;  
    import java.text.SimpleDateFormat;  
    import java.util.Date;  
    /** 
     * 使用ThreadLocal以空間換時間解決SimpleDateFormat線程安全問題。 
     * 
    @author  
     * 
     
    */
      
    public class DateUtil {  
          
        
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";  
          
        @SuppressWarnings(
    "rawtypes")  
        
    private static ThreadLocal threadLocal = new ThreadLocal() {  
            
    protected synchronized Object initialValue() {  
                
    return new SimpleDateFormat(DATE_FORMAT);  
            }
      
        }
    ;  
      
        
    public static DateFormat getDateFormat() {  
            
    return (DateFormat) threadLocal.get();  
        }
      
      
        
    public static Date parse(String textDate) throws ParseException {  
            
    return getDateFormat().parse(textDate);  
        }
      
    }
     

    創(chuàng)建一個ThreadLocal類變量,這里創(chuàng)建時用了一個匿名類,覆蓋了initialValue方法,主要作用是創(chuàng)建時初始化實例。也可以采用下面方式創(chuàng)建

     

        //第一次調(diào)用get將返回null  
        private static ThreadLocal threadLocal = new ThreadLocal();  
        
    //獲取線程的變量副本,如果不覆蓋initialValue,第一次get返回null,故需要初始化一個SimpleDateFormat,并set到threadLocal中  
        public static DateFormat getDateFormat()   
        
    {  
            DateFormat df 
    = (DateFormat) threadLocal.get();  
            
    if(df==null){  
                df 
    = new SimpleDateFormat(DATE_FORMAT)  
                threadLocal.set(df);  
            }
      
            
    return df;  
        }
      


     

    posted on 2011-10-29 17:39 胡鵬 閱讀(1443) 評論(0)  編輯  收藏 所屬分類: java基礎J2EE

    導航

    <2011年10月>
    2526272829301
    2345678
    9101112131415
    16171819202122
    23242526272829
    303112345

    統(tǒng)計

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    agile

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产精品亚洲五月天高清| 黄色网址免费在线观看| www.亚洲精品.com| 成在人线av无码免费高潮喷水 | 91免费人成网站在线观看18| 亚洲一级视频在线观看| 无码专区一va亚洲v专区在线| a视频在线免费观看| 亚洲国产成人精品无码区在线网站| 国产一区二区三区在线免费观看 | 国产高清不卡免费在线| 日本亚洲高清乱码中文在线观看| 国产亚洲AV无码AV男人的天堂| 羞羞网站免费观看| yellow免费网站| 精品免费人成视频app | 国产精品久久久亚洲| 成年女人毛片免费观看97| 在线免费视频你懂的| 亚洲熟妇AV乱码在线观看| 亚洲国产精品无码久久久秋霞2 | 亚洲精品A在线观看| 69pao强力打造免费高清| 国产av无码专区亚洲av毛片搜| 亚洲国产成人久久综合一| 亚洲成A∨人片天堂网无码| 99精品热线在线观看免费视频| 国产偷国产偷亚洲高清在线| 亚洲伊人久久大香线蕉啊| 亚洲国产精品一区二区第一页 | 亚洲黄网站wwwwww| 亚洲综合另类小说色区| 日日夜夜精品免费视频| 97视频免费在线| 免费无码成人AV在线播放不卡| 国产免费一区二区三区免费视频| 久久亚洲欧美国产精品| 亚洲三级在线观看| 亚洲国产综合第一精品小说| 亚洲AV无码国产精品麻豆天美| 久久久久无码专区亚洲av|