日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ThreadLocal的意义和实现

發(fā)布時(shí)間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadLocal的意义和实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

可以想像,如果一個(gè)對(duì)象的可變的變量被多個(gè)線程訪問(wèn)時(shí),必然是不安全的。

  在單線程應(yīng)用可能會(huì)維持一個(gè)全局的數(shù)據(jù)庫(kù)連接,并在程序啟動(dòng)時(shí)初始化這個(gè)連接對(duì)象,從而避免在調(diào)用每個(gè)方法時(shí)都傳遞一個(gè)Connection對(duì)象。ThreadUnsafe類就是這樣做的:

public class ThreadUnsafe {private static Connection connection = DriverManager.getConnection(DB_URL);public void Connection getConnection{ /* 在多線程應(yīng)用中,connection 在被多個(gè)線程訪問(wèn) */return connection;} }

  但是JDBC連接對(duì)象不一定是線程安全的,在多個(gè)線程訪問(wèn)到Connection時(shí),就可能出現(xiàn)安全問(wèn)題。為了解決這個(gè)問(wèn)題,ThreadLocal類提供了安全的做法。

  通過(guò)將JDBC的Connection對(duì)象封裝在ThreadLocal對(duì)象中,當(dāng)每個(gè)線程訪問(wèn)需要Connection對(duì)象時(shí),ThreadLocal對(duì)象返回的是一個(gè)副本。

public class ThreadUnsafe {private static ThreadLocal<Connection> connectionHodler = new ThreadLocal<>{public Connection initialValue() {return DriverManager.getConnection(DB_URL);}} public void Connection getConnection{ /* 即使多個(gè)線程可以訪問(wèn),依然安全 */return connectionHolder.get();} }

ThreadLocal是如何實(shí)現(xiàn)這種功能? 

  首先,在Thread類中有一個(gè)threadLocals的實(shí)例變量,這是一個(gè)Map,保存了與線程相關(guān)的ThreadLocal對(duì)象封裝的變量。

/* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;

  當(dāng)線程初次調(diào)用ThreadLocal對(duì)象的get方法時(shí),就會(huì)調(diào)用initialValue()來(lái)獲取初始值。

/*** 返回ThreadLocal封裝的對(duì)象。*/public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) { /* 首次調(diào)用map為null */ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue(); /* 首次調(diào)用的返回值 */}/*** 初始化封裝在ThreadLocal中對(duì)象的值。*/private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value); //為什么鍵值是ThreadLocal對(duì)象?,因?yàn)橐粋€(gè)線程對(duì)象可能有使用多個(gè)ThreadLocal封閉的變量elsecreateMap(t, value);return value;}/*** 更新封裝在ThreadLocal中對(duì)象的值*/public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);} public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}/*** 創(chuàng)建一個(gè)Map,用于保存ThreadLocal和其封裝的對(duì)象。*/void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue);}

  注意:ThreadLocalMap在ThreadLocal類中聲明,卻是在Thread類中使用的,原因在于,當(dāng)線程結(jié)束時(shí),這些特定于線程的值保存在Thread對(duì)象中,當(dāng)線程終止后,這些值會(huì)作為垃圾回收。

  ThreadLocal類實(shí)現(xiàn)的是一種線程封閉技術(shù)。將變量封閉在單線程中,從而避免同步。

參考:?《Java?Concurrency?in?Practice》?P35&P37?

?

轉(zhuǎn)載于:https://www.cnblogs.com/yvkm/p/10664109.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的ThreadLocal的意义和实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。