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",后續還需要處理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM