ThreadLocal之我所見

      網友投稿 640 2025-04-01

      網上有很多關于ThreadLocal的文章,大部分都提到了多線程之間共享資源的問題。其實ThreadLocal和多線程之間一點關系都沒有。如果有,我怕是它的名字改成ThreadShare是不是更合適呢?開個玩笑。從其名稱ThreadLocal,我們就可以看出他應該是隸屬于線程內部的資源。接下來就詳細說說吧。

      我們以前在處理一個Request請求,穿透多個業務方法的時候,如果要共享數據,一般都會搞個Context上下文對象,在多個方法之間進行傳遞,這樣可以解決多個方法之間的數據共享問題。這是很不錯的一種方案,而且這種方案在實際使用的時候效果也非常不錯,因為Context內部我們想放什么,就放什么,想怎么放就怎么放,非常的自由無界。但是這種自由帶來的問題在小流量的請求中是不會有問題的,但是在大流量的請求中,則存在不小的問題,主要在:

      1. Context對象,每個請求進來,都會new一個,大流量下,瞬間暴增,由于空間申請操作勢必引發頻繁的young GC, 業務壓力大的時候,full GC也是不可避免的。

      2. Context對象,在一個請求終結之后,需要手動釋放。

      3. Context對象,存在被請求內部的多線程共享訪問的情形。有線程安全性問題。

      上面三個問題,是我隨便列舉的,但是在實際使用中,可能還有更多。但是如果Context的生產和銷毀如果控制的足夠好的話,上面的問題也不是什么問題。

      既然Context對象的控制稍顯麻煩,那么JDK有沒有提供什么現成的類庫供我們使用呢? 答案是肯定的,這個對象就是ThreadLocal對象。

      說道ThreadLocal對象,我更認為他是在當前請求的上游和下游之間進行數據共享的。那么按照之前的例子說來,如果一個請求穿越多個業務方法,其實數據的共享可以利用ThreadLocal來進行,這樣就無需專門定義一個Context。

      ThreadLocal之我所見

      首先來看看其內部get實現機制:

      /**?*?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(); } ThreadLocalMap?getMap(Thread?t)?{????return?t.threadLocals; }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; }protected?T?initialValue()?{????return?null; }

      從上面源碼可以看出,get操作會從當前Thread上附加的map中進行數據獲取。

      再來看看set方法:

      /**?*?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)?{ ????Thread?t?=?Thread.currentThread(); ????ThreadLocalMap?map?=?getMap(t);????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); }

      從上面源碼看出,首先他會取出當前Thread,然后會將map設置到當前Thread上,用戶可以在這個map上進行數據增刪改查操作。非常巧妙。所以從這里可以看出,一個ThreadLocal對象,即便穿插在多個線程之間,也不會造成資源共享問題,因為他會為每個線程都設置map對象,這也從根本上避免了線程安全問題。

      最后,因為ThreadLocal內部的對象為WeakReference,所以不用進行手動釋放,只需要保證一個請求結束,對其內部的引用釋放掉就行了,然后自動會被JVM優先處理掉,根本無需擔心內存泄露問題。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel函數教程—運用TEXT函數顯示日期為星期幾
      下一篇:Excel2016表格中怎么設計經典的收據單?
      相關文章
      亚洲深深色噜噜狠狠网站| 无码色偷偷亚洲国内自拍| 国产99久久亚洲综合精品| 国产日本亚洲一区二区三区| 久久久久久亚洲Av无码精品专口| 亚洲乱码日产一区三区| 久久久久亚洲精品男人的天堂| 亚洲国产精品成人AV无码久久综合影院| 亚洲色欲色欲www在线播放| 亚洲无人区码一二三码区别图片| 亚洲丝袜中文字幕| 亚洲一区免费在线观看| 亚洲自国产拍揄拍| 亚洲一区二区三区高清在线观看| 中文字幕亚洲男人的天堂网络 | 亚洲制服丝袜第一页| 亚洲一区二区三区久久久久| 亚洲mv国产精品mv日本mv| 亚洲伊人久久大香线蕉结合| 亚洲一本之道高清乱码| 天天爽亚洲中文字幕| 日本亚洲色大成网站www久久| 亚洲一级毛片视频| 亚洲va久久久久| 亚洲综合av一区二区三区不卡 | 国产国拍亚洲精品福利| 精品亚洲成A人在线观看青青| 免费亚洲视频在线观看| 亚洲AV无码乱码在线观看| 亚洲人午夜射精精品日韩| 亚洲中文字幕无码久久精品1| 亚洲色爱图小说专区| 亚洲AV日韩AV天堂久久| 亚洲欧洲日产v特级毛片| 国产AV旡码专区亚洲AV苍井空| 亚洲成a∧人片在线观看无码| 久久无码av亚洲精品色午夜| 国产亚洲精品成人久久网站| 亚洲高清无码专区视频| 黑人精品videos亚洲人| 亚洲视频在线免费播放|