zoukankan      html  css  js  c++  java
  • ThreadLocal

    在多线程环境中对于全局变量的使用,往往这个变量存在线程不安全性,通过将对象保存在ThreadLocal中,使得每个线程都拥有自己的对象,达到维持线程封闭性效果。

    生产环境中的案例:

    • 登录 一般登录实现会选择在登录成功后 将user上下文对象封装在ThreadLocal对象内  ,其他线程需要用到登录的用户ID

    说明

    一般都会在

    HandlerInterceptorAdapter中preHandle方法内 每次从ThreadLocal.get上下文对象 然后重新设置新的内容
    public static void setContext(CmsUserTokenVO cmsUserTokenVO) {
            CmsUserSession.Context context = getContext();
            context.setToken(cmsUserTokenVO.getToken());
            context.setUserId(cmsUserTokenVO.getUserId());
            context.setUserName(cmsUserTokenVO.getUserName());
            context.setUserType(cmsUserTokenVO.getUserType());
        }
    
        public static CmsUserSession.Context getContext() {
            return LOCAL.get();
        }
    • dubbo traceId的使用

    消费者项目访问线程  在调用完dubbo服务后  拿到traceId并且放到threadLocal变量内  ,于是该线程可以直接获取生产者线程的TraceId方便  分布式traceId日志跟踪  排查问题

    /**
    *生产者
    */
    public class TraceIDProviderFilter implements Filter { public static final String TRACE_ID = "TRACE_ID"; public TraceIDProviderFilter() { } public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException { String traceId = inv.getAttachment("TRACE_ID"); if (StringUtils.isEmpty(traceId)) { traceId = UUID.randomUUID().toString(); } TraceIDUtils.setTraceId(traceId); String mdcData = String.format("[TraceID:%s]", traceId); MDC.put("mdcData", mdcData); Result var5; try { var5 = invoker.invoke(inv); } finally { TraceIDUtils.removeTraceId(); MDC.clear(); } return var5; } }
    /**
    *消费者
    */
    @Activate(
    group = {"consumer"}
    )
    public class TraceIDConsumerFilter implements Filter {
    public TraceIDConsumerFilter() {
    }

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    if (TraceIDUtils.getTraceId() != null) {
    invocation.getAttachments().put("TRACE_ID", TraceIDUtils.getTraceId());
    }

    return invoker.invoke(invocation);
    }
    }
     

    示例代码

    public class TraceIDUtils {
    
        private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<String>();
    
        public static String getTraceId() {
            return TRACE_ID.get();
        }
    
        public static void setTraceId(String traceId) {
            TRACE_ID.set(traceId);
        }
    
        public static void removeTraceId() {
            TRACE_ID.remove();
        }
    
    }

    注意:

    volatile变量上存在一种特殊的线程封闭。只要确保只有单个线程对共享的volatile变量执行写入操作,那么就可以完全的在这些共享volatile变量上执行“读取-修改-写入”操作.

    在这种情况下 相当于将修改操作封闭在单个线程中以防止发生竞争条件,并且volatile变量的可见性还能确保其他线程能看到最新的值。

  • 相关阅读:
    ⑬linux基础命令 wget
    爱情的诗·21~25节
    爱情的诗·16~20节
    爱情的诗·11~15节
    人生的诗·406~410节
    唐诗宋词学习·126~130节
    爱情的诗·6~10节
    人生的诗·401~405节
    唐诗宋词学习·121~125节
    唐诗宋词学习·100~105节
  • 原文地址:https://www.cnblogs.com/zhangfengshi/p/7120149.html
Copyright © 2011-2022 走看看