隨筆 - 2  文章 - 2  trackbacks - 0
          <2014年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          留言簿

          隨筆檔案(1)

          文章分類(16)

          最新隨筆

          搜索

          •  

          最新評論

          ThreadLocal是為了使每個線程保存一份屬于自己的數據。

          先看一個使用ThreadLocal的實例。

          package org.springframework.aop.framework;

          import org.springframework.core.NamedThreadLocal;

          public abstract class AopContext {

              
          private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy");

              
          public static Object currentProxy() throws IllegalStateException {
                  Object proxy 
          = currentProxy.get();
                  
          if (proxy == null) {
                      
          throw new IllegalStateException(
                              
          "Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
                  }
                  
          return proxy;
              }

              
          static Object setCurrentProxy(Object proxy) {
                  Object old 
          = currentProxy.get();
                  
          if (proxy != null) {
                      currentProxy.set(proxy);
                  }
                  
          else {
                      currentProxy.remove();
                  }
                  
          return old;
              }

          }

          上例展示的是spring框架中獲取當前線程的代理對象的方法,AopContext.currentProxy(),在本線程的程序調用棧中只要調用AopContext的靜態方法就可以獲取本線程相關的代理對象。如果不用ThreadLocal,那么這個代理對象在創建后,就要一層層傳遞下去,才能在后面獲取到并使用。
          通過這個例子,我們可以知道[b]ThreadLocal主要是提供了一種保持對象的方法以及避免了對象在程序調用中傳遞的簡便訪問方法。ThreadLocal與共享數據和同步沒有明顯關系。[/b]

          下面看看相關的源碼以了解具體的結構。
          public class Thread implements Runnable {
              
          // ThreadLocalMap是一個以ThreadLocal為key,Object為值的map,由ThreadLocal維護
                  ThreadLocal.ThreadLocalMap threadLocals = null;
          }

          從Thread的源碼中可以得知,是每一個Thread持有一個自己的map,并不是一個ThreadLocal持有一個map。


          public class ThreadLocal<T> {

           
          public T get() {
              
          // 獲取當前線程
                  Thread t = Thread.currentThread();
              
          // 獲取當前線程的threadLocals變量
                  ThreadLocalMap map = getMap(t);
              
          // 從當前線程的threadLocals變量中取得本threadLocal為key的值
                  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;
              }
              
             
               
          public void set(T value) {
              
          // 獲取當前線程
                  Thread t = Thread.currentThread();
              
          // 獲取當前線程的threadLocals變量
                  ThreadLocalMap map = getMap(t);
              
          // 以本threadLocal為key的保存值到當前線程的threadLocals變量中去
                  if (map != null)
                      map.set(
          this, value);
                  
          else
                      createMap(t, value);
              }
              
               ThreadLocalMap getMap(Thread t) {
                  
          return t.threadLocals;
              }
              
               
          void createMap(Thread t, T firstValue) {
                  t.threadLocals 
          = new ThreadLocalMap(this, firstValue);
              }
          }

          使用ThreadLocal過程: 對于每一個需要線程保存自身實例的變量,需要定義一個靜態的ThreadLocal實例。然后將一個共用的ThreadLocal靜態實例作為key,將不同對象的引用保存到不同線程的ThreadLocalMap中,然后在線程執行的各處通過這個靜態ThreadLocal實例的get()方法取得自己線程保存的那個對象。
          此外,每個線程保存的自身數據并不是通過備份或復制的,而是new創建出來的。

          通過ThreadLocal各個線程只能獲取自身對應的數據,不能訪問其他線程的數據,但是如果兩個線程在set時引用了同一個數據,仍然存在同步問題。
          posted on 2011-03-31 14:05 liucs 閱讀(2846) 評論(0)  編輯  收藏 所屬分類: 多線程與并發

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 台北市| 桐柏县| 吉木乃县| 望江县| 山西省| 贡嘎县| 张家口市| 华宁县| 无极县| 高安市| 聂拉木县| 兴和县| 云霄县| 齐河县| 金昌市| 白水县| 南郑县| 普安县| 河东区| 蛟河市| 大厂| 江达县| 灵山县| 临潭县| 祁阳县| 嫩江县| 孝义市| 深泽县| 施甸县| 邵武市| 彩票| 黎川县| 游戏| 铅山县| 白河县| 邳州市| 溆浦县| 合江县| 航空| 兰坪| 丽水市|