隨筆 - 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)  編輯  收藏 所屬分類: 多線程與并發

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


          網站導航:
           
          主站蜘蛛池模板: 正阳县| 思南县| 德清县| 苍梧县| 肥西县| 安新县| 新津县| 肇州县| 红安县| 泾川县| 五寨县| 松溪县| 恩平市| 福泉市| 天全县| 黎平县| 天峨县| 昌邑市| 邵武市| 和顺县| 北票市| 黔东| 丁青县| 四会市| 建阳市| 巍山| 绥宁县| 平陆县| 墨玉县| 永新县| 两当县| 延吉市| 高清| 柘荣县| 洪雅县| 瓦房店市| 贞丰县| 新竹县| 河曲县| 无锡市| 休宁县|