之前一直使用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却是每个线程都不一样的。看如下分析:
新闻热点
疑难解答