1. 程式人生 > 實用技巧 >ThreadLocal應用及理解

ThreadLocal應用及理解

轉載請註明出處:

  1. 先展示threadLocal的一個簡單封裝,該封裝用來在不同的請求執行緒中解析使用者引數。在請求經過過濾器時,

對使用者的資訊進行設定入ThreadLocalContext 中,可在同一個請求的不同業務中獲取使用者的資訊引數。

import com.homepage.UserInfo;

public class ThreadLocalContext {

    private static ThreadLocal<UserInfo> userThreadLocal = new ThreadLocal<>();

    public static
UserInfo getThreadLocalContext(){ UserInfo user = userThreadLocal.get(); if (user == null){ return new UserInfo(); } return user; } public static void setUserThreadLocal(UserInfo user){ userThreadLocal.set(user); } public static
void clear(){ userThreadLocal.remove(); } }

  以上為ThreadLocal的一個簡單封裝。

  2. 使用的場景主要為:

  • 每個執行緒需要有自己單獨的例項
  • 例項需要在多個方法中共享,但不希望被多執行緒共享

  3.原理:

     每個執行的執行緒都會有一個型別為ThreadLocal.ThreadLocalMap的map,這個map就是用來儲存與這個執行緒繫結的變數,

    map的key就是ThreadLocal物件,value就是執行緒正在執行的任務中的某個變數的包裝類Entry。可以通過set方法來看threadLocal實現的原理:

/**
     * 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);
    }

  

4.ThreadLocal作用:

    在多執行緒程式中,同一個執行緒在某個時間段只能處理一個任務.我們希望在這個時間段內,任務的某些變數能夠和處理它的執行緒進行繫結,

  在任務需要使用這個變數的時候,這個變數能夠方便的從執行緒中取出來.ThreadLocal能很好的滿足這個需求,用ThreadLocal變數的程式看起來

  也會簡潔很多,因為減少了變數在程式中的傳遞。

5. 為什麼ThreadLocalMap的Entry是一個weakReference?   使用weakReference,能夠在ThreadLocal失去強引用的時候,ThreadLocal對應的Entry能夠在下次gc時被回收,回收後的空間能夠得到複用,   在一定程度下能夠避免記憶體洩露. 6. 使用ThreadLocal應該注意什麼?   在使用ThreadLocal物件,儘量使用static,不然會使執行緒的ThreadLocalMap產生太多Entry,從而造成記憶體洩露