国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java線程(篇外篇):線程本地變量ThreadLocal

2019-11-14 11:27:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

       首先說(shuō)明ThreadLocal存放的值是線程內(nèi)共享的,線程間互斥的,主要用于線程內(nèi)共享一些數(shù)據(jù),避免通過(guò)參數(shù)來(lái)傳遞,這樣處理后,能夠優(yōu)雅的解決一些實(shí)際問(wèn)題,比如hibernate中的OpensessionInView,就是使用ThreadLocal保存Session對(duì)象,還有我們經(jīng)常用ThreadLocal存放Connection,代碼如:

[java] view plain copy PRint?/**  * 數(shù)據(jù)庫(kù)連接管理類  * @author 爽  *  */  public class ConnectionManager {        /** 線程內(nèi)共享Connection,ThreadLocal通常是全局的,支持泛型 */      private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();            public static Connection getCurrConnection() {          // 獲取當(dāng)前線程內(nèi)共享的Connection          Connection conn = threadLocal.get();          try {              // 判斷連接是否可用              if(conn == null || conn.isClosed()) {                  // 創(chuàng)建新的Connection賦值給conn(略)                  // 保存Connection                  threadLocal.set(conn);              }          } catch (SQLException e) {              // 異常處理          }          return conn;      }            /**      * 關(guān)閉當(dāng)前數(shù)據(jù)庫(kù)連接      */      public static void close() {          // 獲取當(dāng)前線程內(nèi)共享的Connection          Connection conn = threadLocal.get();          try {              // 判斷是否已經(jīng)關(guān)閉              if(conn != null && !conn.isClosed()) {                  // 關(guān)閉資源                  conn.close();                  // 移除Connection                  threadLocal.remove();                  conn = null;              }          } catch (SQLException e) {              // 異常處理          }      }  }  

       這樣處理的好處:

統(tǒng)一管理Connection;不需要顯示傳參Connection,代碼更優(yōu)雅;降低耦合性。

       ThreadLocal有四個(gè)方法,分別為:

initialValue

protected T initialValue()返回此線程局部變量的當(dāng)前線程的初始值。最多在每次訪問(wèn)線程來(lái)獲得每個(gè)線程局部變量時(shí)調(diào)用此方法一次,即線程第一次使用 get() 方法訪問(wèn)變量的時(shí)候。如果線程先于 get 方法調(diào)用 set(T) 方法,則不會(huì)在線程中再調(diào)用 initialValue 方法。

該實(shí)現(xiàn)只返回 null;如果程序員希望將線程局部變量初始化為 null 以外的某個(gè)值,則必須為 ThreadLocal創(chuàng)建子類,并重寫此方法。通常,將使用匿名內(nèi)部類。initialValue 的典型實(shí)現(xiàn)將調(diào)用一個(gè)適當(dāng)?shù)臉?gòu)造方法,并返回新構(gòu)造的對(duì)象。

返回:返回此線程局部變量的初始值

get

public T get()返回此線程局部變量的當(dāng)前線程副本中的值。如果這是線程第一次調(diào)用該方法,則創(chuàng)建并初始化此副本。

返回:此線程局部變量的當(dāng)前線程的值

set

public void set(T value)將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為指定值。許多應(yīng)用程序不需要這項(xiàng)功能,它們只依賴于initialValue() 方法來(lái)設(shè)置線程局部變量的值。

參數(shù):value - 存儲(chǔ)在此線程局部變量的當(dāng)前線程副本中的值。

remove

public void remove()移除此線程局部變量的值。這可能有助于減少線程局部變量的存儲(chǔ)需求。如果再次訪問(wèn)此線程局部變量,那么在默認(rèn)情況下它將擁有其 initialValue

       很多人對(duì)ThreadLocal存在一定的誤解,說(shuō)ThreadLocal中有一個(gè)全局的Map,set時(shí)執(zhí)行map.put(Thread.currentThread(), value),get和remove時(shí)也同理,但SUN的大師們是否是如此實(shí)現(xiàn)的,我們只能去看源碼了。

       set方法:

[java] view plain copy print?/**  * Sets the current thread's copy of this thread-local variable  * to the specified value.  Most subclasses will have no need to  * override this method, relying solely on the {@link #initialValue}  * method to set the values of thread-locals.  *  * @param value the value to be stored in the current thread's copy of  *        this thread-local.  */  public void set(T value) {      // 獲取當(dāng)前線程對(duì)象      Thread t = Thread.currentThread();      // 獲取當(dāng)前線程本地變量Map      ThreadLocalMap map = getMap(t);      // map不為空      if (map != null)          // 存值          map.set(this, value);      else          // 創(chuàng)建一個(gè)當(dāng)前線程本地變量Map          createMap(t, value);  }    /**  * Get the map associated with a ThreadLocal. Overridden in  * InheritableThreadLocal.  *  * @param  t the current thread  * @return the map  */  ThreadLocalMap getMap(Thread t) {      // 獲取當(dāng)前線程的本地變量Map      return t.threadLocals;  }  

       這里注意,ThreadLocal中是有一個(gè)Map,但這個(gè)Map不是我們平時(shí)使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個(gè)內(nèi)部類,不對(duì)外使用的。當(dāng)使用ThreadLocal存值時(shí),首先是獲取到當(dāng)前線程對(duì)象,然后獲取到當(dāng)前線程本地變量Map,最后將當(dāng)前使用的ThreadLocal和傳入的值放到Map中,也就是說(shuō)ThreadLocalMap中存的值是[ThreadLocal對(duì)象, 存放的值],這樣做的好處是,每個(gè)線程都對(duì)應(yīng)一個(gè)本地變量的Map,所以一個(gè)線程可以存在多個(gè)線程本地變量

       get方法:

[java] view plain copy print?/**  * Returns the value in the current thread's copy of this  * thread-local variable.  If the variable has no value for the  * current thread, it is first initialized to the value returned  * by an invocation of the {@link #initialValue} method.  *  * @return the current thread's value of this thread-local  */  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();  }         有了之前set方法的分析,get方法也同理,需要說(shuō)明的是,如果沒(méi)有進(jìn)行過(guò)set操作,那從ThreadLocalMap中拿到的值就是null,這時(shí)get方法會(huì)返回初始值,也就是調(diào)用initialValue()方法,ThreadLocal中這個(gè)方法默認(rèn)返回null。當(dāng)我們有需要第一次get時(shí)就能得到一個(gè)值時(shí),可以繼承ThreadLocal,并且覆蓋initialValue()方法。

       (完)

       本文來(lái)自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/15732053


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 兰溪市| 德阳市| 佳木斯市| 丹阳市| 马尔康县| 铜陵市| 出国| 噶尔县| 仪陇县| 石柱| 肥西县| 自贡市| 郴州市| 中西区| 墨竹工卡县| 广东省| 巩义市| 扶余县| 前郭尔| 平利县| 红原县| 霍邱县| 远安县| 石楼县| 宜宾县| 乡城县| 双柏县| 成安县| 苗栗县| 阳原县| 大石桥市| 新昌县| 图木舒克市| 固镇县| 榆林市| 万载县| 河源市| 安康市| 巴中市| 平塘县| 仙桃市|