ThreadLocalMap裡Entry為何宣告為WeakReference?
Java裡,每個執行緒都有自己的ThreadLocalMap,裡邊存著自己私有的物件。Map的Entry裡,key為ThreadLocal物件,value即為私有物件T。在spring MVC中,常用ThreadLocal儲存當前登陸使用者資訊,這樣執行緒在任意地方都可以取到使用者資訊了。
public class UserContext { private static final ThreadLocal<UserInfo> userInfoLocal = new ThreadLocal<UserInfo>(); public static UserInfo getUserInfo() {return userInfoLocal.get(); } public static void setUserInfo(UserInfo userInfo) { userInfoLocal.set(userInfo); } public static void clear() { userInfoLocal.remove(); } }
這裡,跳過ThreadLocal和ThreadLocalMap的工作原理及場景不講,主要來說說Entry為什麼是WeakReference?
/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows.*/ static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } }
先來看看WeakReference的作用,百度一下:
WeakReference是Java語言規範中為了區別直接的物件引用(程式中通過建構函式宣告出來的物件引用)而定義的另外一種引用關係。WeakReference標誌性的特點是:reference例項不會影響到被應用物件的GC回收行為(即只要物件被除WeakReference物件之外所有的物件解除引用後,該物件便可以被GC回收),只不過在被物件回收之後,reference例項想獲得被應用的物件時程式會返回null。
我的理解就是,WeakReference對應用的物件userInfoLocal是弱引用,不會影響到userInfoLocal的GC行為。如果是強引用的話,線上程執行過程中,我們不再使用userInfoLocal了,將userInfoLocal置為null,但userInfoLocal線上程的ThreadLocalMap裡還有引用,導致其無法被GC回收(當然,可以等到執行緒執行結束後,整個Map都會被回收,但很多執行緒要執行很久,如果等到執行緒結束,便會一直佔著記憶體空間)。而Entry宣告為WeakReference,userInfoLocal置為null後,執行緒的threadLocalMap就不算強引用了,userInfoLocal就可以被GC回收了。map的後續操作中,也會逐漸把對應的"stale entry"清理出去,避免記憶體洩漏。
所以,我們在使用完ThreadLocal變數時,儘量用threadLocal.remove()來清除,避免threadLocal=null的操作。前者remove()會同時清除掉執行緒threadLocalMap裡的entry,算是徹底清除;而後者雖然釋放掉了threadLocal,但線種threadLocalMap裡還有其"stale entry",後續還需要處理。
相關推薦
ThreadLocalMap裡Entry為何宣告為WeakReference?
Java裡,每個執行緒都有自己的ThreadLocalMap,裡邊存著自己私有的物件。Map的Entry裡,key為ThreadLocal物件,value即為私有物件T。在spring MVC中,常用ThreadLocal儲存當前登陸使用者資訊,這樣執行緒在任意地方都可以取到使用者資訊了。 public
ThreadLocal型別變數為何宣告為靜態?- ThreadLocal實現原理
/** * Sets the current thread's copy of this thread-local variable * to the specified value. Most subclasses will have no need to * overrid
解構函式為什麼不能宣告為虛擬函式?解構函式為什麼要宣告為虛擬函式
多型中的虛擬函式表是在執行時建立的還是編譯時建立的? 答:虛擬函式表在編譯的時候就確定了,而類物件的虛擬函式指標vptr是在執行階段確定的,這是實現多型的關鍵 (類的函式的呼叫並不是在編譯時就確定的,而是在執行時才確定的,由於編寫程式碼的時候並不能確定被呼叫的是基類的函式還是哪個派生類的函式,所以宣告為虛
一文看懂為何華為停止社招
一文看懂為何華為停止社招 百家號10-24 近日,關於國內通訊裝置巨頭華為公司停止社招的傳聞,引來眾多人士關注,一時之間,通訊行業冬天論再次捲土重來。雖然華為公司的“狼性文化”和“加班文化”一直為人詬病, 但其提供的遠超同行的薪資待遇、全球電信裝置市場領頭羊的廣闊舞臺和“高大上”的工
C++函式中那些不可以被宣告為虛擬函式的函式
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
effective c++條款22:將成員變數宣告為private
將成員變數宣告為private的三大理由: 1. 提供語法一致性: 如果將所有的變數都宣告為private,那麼當其他人使用這個類時,就不用糾結是以函式方式呼叫還是變數方式呼叫,更加節省時間。 #include <iostream> using namespa
struts標籤怎麼判斷request裡的屬性是否為空 <s:if test="${list==null}"> </s:if>
<s:if test="${weigou}==999"> //錯誤的 ${list==null} ,$實在strtus的配置檔案中取值用的,不是在jsp頁面裡取值的的吧,所以上面錯誤; 下面是對的 <s:if test="#request.weigou==999}"
yii2 位址列裡 %2 如何修改為 /
一、 開啟\vendor\yiisoft\yii2\web\UrlManager.php 二、將第371行的程式碼註釋調整為如下即可 //$url = "$baseUrl?{$this->routeParam}=" . urlencode($route); $url = "$base
為何譯為“東家機”和“賓客機”
學習過虛擬化、雲端計算的人大概都知道,並且都在自己的電腦上安裝KVM,如下圖所示: 什麼情況?不過是在物理機的Windows 10上安裝了VMware;在VMware上安裝了Linux CentOS 7作業系統;又在其上安裝了Qemu + KVM虛擬化環境;然後又在這個環境裡三個虛擬機器裡
const 將變數宣告為常量
const type-name cinstant -name 將變數宣告為常量 #include<iostream> int main() { using namespace std; const int Pi = 22.0 / 7; cout
【Java】從內部類中訪問變數,需要宣告為final
Cannot refer to a non-final variable ‘result’ inside an inner class defined in a different method 從內部類中訪問變數’result’,需要宣告為final 這
Java匿名內部類中使用外部類方法的形參或區域性變數必須宣告為final
對於這個問題,首先我們應該明確的一點是對於匿名內部類,它可能引用三種外部變數:外部類的成員變數外部方法或作用域內的區域性變數外部方法的引數而第一種變數是不需要宣告為final的,但後兩種是需要宣告為final的。那這是為什麼呢?不急,我們首先來看第一個知識點。知識點一,匿名內部類同所有類一
內部類中引用的變數必須要宣告為final的原因
查了下看到有人說原因如下: 區域性匿名類在原始碼編譯後也是要生成對應的class檔案的(一般會是A$1.class這種形式的檔案),那麼這個二進位制檔案是獨立於其外圍類(A.class)的,就是說它無法知道A類中方法的變數。但是A$1.class又確實要訪問A類對應方法的區域性變數的值。。。怎麼辦呢?
為什麼內部類中有static成員時內部類也必須宣告為static
如果A和B類關係緊密,且A類的主要作用是幫助完成B類的實現,這時可將A類作為B類的內部類,兩個類可以互相訪問各自的私有成員,這樣就方便B類的設計,使B類更加自給自足(self contained)。http://www.tanhuanyao.com h
windows下VS使用FFmpeg被宣告為已否決的解決方案
FFmpeg被宣告為已否決的解決方案 環境: 系統:Win10 環境:VS2015 64bit 原因 FFmpeg中所謂的“被宣告為已否決”就是因為函式或者結構體屬性被標示為attribute_deprecated,很有可能在未來的版本中就刪
ArrayList的陣列宣告為transient卻依舊序列化的原因
ArrayList是會開闢多餘空間來儲存資料的,而系列化和反序列化這些沒有存放資料的空間是要消耗更多資源的,所以ArrayList的陣列就宣告為transient,告訴虛擬機器這個你別管,我自己來處理
FFmpeg 被宣告為已否決 deprecated(2018 精)
PIX_FMT_YUV420P -> AV_PIX_FMT_YUV420P'AVStream::codec': 被宣告為已否決:if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){=>if(pForm
變數i'是從內部類中訪問的,需要宣告為fina
要解決的問題如標題,今天在寫一個執行緒的時候希望可以迴圈讓執行緒執行5次,出現了這個錯誤 錯誤翻譯過來就是 變數i’是從內部類中訪問的,需要宣告為fina,這是為什麼呢? 思索了半天,又上百度搜索,終於明白是為什麼了,其實問題也很簡單因為執行緒本身就是一個內部類,內部類和它外面的類在編譯的
在工程.h 檔案了定義了變數,依然在.cpp檔案裡報 未宣告的變數,無法識別的識別符號錯誤
實際應用中總會遇到各種錯誤,比如我在.h檔案裡定義了一個結構體,並且.cpp檔案包含了該標頭檔案,結果在標頭檔案裡使用,卻無法識別該型別。百思不得其解,後來才發現,原理是這樣子的。 1, 我標
vs2013error C4996: 'GetVersionExW': 被宣告為已否決
嘗試這個1.Project Properties > Configuration Properties > C/C++ > General > SDL checks關掉其他方法:2.#pragma warning(disable: 4996)