之前一直使用ThreadLocal進行請求上下文的設置,只知道ThreadLocal是線程安全的每個線程獲取的是本線程所對應的值,沒有去深入了解ThreadLocal的具體實現,現在翻看轉載的博客并參照源碼,徹底明白了其原理,記錄如下。
先看如下業務代碼:
/** * 應用基本上下文 * @author rambo.pan */public class HttpContext { /** * 靜態變量,作為各個線程中的Map的key,每個HttpContext實例為相應的value */ PRivate static final ThreadLocal<HttpContext> currentContext = new ThreadLocal<HttpContext>(); private boolean isLogin; private String userId; private UserInfo userInfo; private VpalRequestHeader header; private String client; /** * 獲取ThreadLocal中當前線程對應的HttpContext實例 * @param throwFlag set方法傳入false,當context為空時new一個新實例;get方法傳入true,當context為空時throw異常 * @return */ private static HttpContext getContext(boolean throwFlag){ HttpContext context = currentContext.get(); if (context == null) { if (throwFlag) { throw new RuntimeException("context can not be access now"); }else { context = new HttpContext(); } } return context; } /** * 獲取ThreadLocal中當前線程對應的HttpContext實例:用戶登錄標識 * @return */ public static boolean isLogin() { HttpContext context = getContext(true); return context.isLogin; }}我以前的理解是:ThreadLocal實例是和線程關聯的,每個線程有單獨的ThreadLocal實例,所以對ThreadLocal定義成static final 感到很不理解,因為這樣定義就表明:當HttpContext的字節碼被裝載入虛擬機的時候,其類變量currentContext就會被初始化且僅初始化一次,那么每個線程用key都是一樣的了啊,如此推斷每個線程拿到的value也都是一樣的了。 實際上,這個理解的前半段是沒問題的,偏差出現在后面,key雖然是一樣的,但是Map卻是每個線程都不一樣的。看如下分析:
|
新聞熱點
疑難解答