多線程之---ThreadLocal

1、使用  通過set()方法設置屬性,通過get()方法獲取,remove()方法刪除
2、源碼:get()--獲取
        public T get() {
               Thread t = Thread.currentThread();//獲取當前線程
               ThreadLocalMap map = getMap(t);///獲得當前線程裏面的局部變量ThreadLocal.ThreadLocalMap
               if (map != null) {
                   ThreadLocalMap.Entry e = map.getEntry(this);//map存在 通過this 獲取對應的value值
                   if (e != null) {
                       @SuppressWarnings("unchecked")
                       T result = (T)e.value;
                       return result;
                   }
               }
               return setInitialValue();//
           }

    //getMap方法
 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;//獲得是Thread類的局部變量
    }
    //設置初始值  通過重新這個方法 來設置初始值
  protected T initialValue() {
        return null;
    }
    remove():---刪除
    public void remove() {
             ThreadLocalMap m = getMap(Thread.currentThread());//根據當前線程獲取ThreadLocalMap
             if (m != null)
                 m.remove(this);//刪除對應的key值
         }
    set();---設置
     public void set(T value) {
            Thread t = Thread.currentThread();//獲取當前線程
            ThreadLocalMap map = getMap(t);//獲取當前線程的局部變量ThreadLocalMap
            if (map != null)
                map.set(this, value);//設置key值爲當前ThreadLocal變量 value值爲變量value
            else
                createMap(t, value);
        }
       初始化的時候 創建map方法:
void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

跟ThreadLocalMap關係:----ThreadLocal裏面的一個內部類 key值爲ThreadLocal變量 value爲要保存的變量值
        1、在每個線程Thread內部有一個ThreadLocal.ThreadLocalMap類型的成員變量threadLocals,
        threadLocals就是用來存儲實際的變量副本的,鍵值爲當前ThreadLocal變量,value爲變量副本(即T類型的變量)。
        2、初始時,在Thread裏面,threadLocals爲空,當通過ThreadLocal變量調用get()方法或者set()方法,就會對Thread類中的threadLocals進行初始化
        ,並且以當前ThreadLocal變量爲鍵值,以ThreadLocal要保存的副本變量爲value,存到threadLocals。
        3、在當前線程裏面,如果要使用副本變量,就可以通過get方法在threadLocals裏面查找。

3、ThreadLocal不是用來解決共享對象的多線程訪問問題,他是保證線程安全的方式---線程封閉的應用之一。【通過set()方法放到線程中的對象是
   該線程自己使用的對象,其他線程訪問不了的;通過get()方法  各線程從自己的map裏面獲取放進去的對象;通過threadLocal作爲key值 每個線程中可有多個threadLocal變量,在
   每個線程裏面的threadLocalMap裏面 設置多個】
   應用場景:解決 數據庫連接、Session管理
    private static final ThreadLocal threadSession = new ThreadLocal();

    public static Session getSession() throws InfrastructureException {
        Session s = (Session) threadSession.get();
        try {
            if (s == null) {
                s = getSessionFactory().openSession();
                threadSession.set(s);
            }
        } catch (HibernateException ex) {
            throw new InfrastructureException(ex);
        }
        return s;
    }
ThreadLocal不是用來解決對象共享訪問問題的,而主要是提供了保持對象的方法和避免參數傳遞的方便的對象訪問方式【空間換時間 保證線程安全的一種方式】。歸納了兩點:
1。每個線程中都有一個自己的ThreadLocalMap類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。
2。將一個共用的ThreadLocal靜態實例作爲key,將不同對象的引用保存到不同線程的ThreadLocalMap中,然後在線程執行的各處通過這個靜態ThreadLocal實例的get()方法取得自己線程保存的那個對象,避免了將這個對象作爲參數傳遞的麻煩。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章