ThreadLocal——线程变量实现线程隔离

一、ThreadLocal简介
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:

  • 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
  • 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。

ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。
 

举例:

/**
 * 请求信息线程变量
*/
@Data
public class RequestInfoContext {
    private String value1;

    private String value2;
}
/**
 * 请求信息线程变量持有者
 */
public class RequestInfoContextHolder {
    private static final ThreadLocal CONTEXT = new TransmittableThreadLocal<>();

    public static void set(RequestInfoContext requestInfoContext) {
        CONTEXT.set(requestInfoContext);
    }

    public static RequestInfoContext get() {
        return CONTEXT.get();
    }

    public static void clear() {
        CONTEXT.remove();
    }
}
/**
 * 切面中添加
 */
@Aspect
@Component
@Slf4j
public class ControllerAspect {

    @Pointcut("execution(* cn.fj.dp.controller.*.*(..))")
    public void pointCut(){

    }
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            RequestInfoContext requestInfoContext = new RequestInfoContext();

            // token校验
            String token = request.getHeader("value1");
            requestInfoContext.setValue1(value1);

            // 平台id校验
            String platform = request.getHeader("value2");

            requestInfoContext.setValue2(value2);

            log.info("request data:" + JSONUtil.toJsonStr(requestInfoContext));
            // 执行方法
            RequestInfoContextHolder.set(requestInfoContext);
            Object result = proceedingJoinPoint.proceed();
            return result;
        } catch (Exception e) {
            log.error("doAround,Error", e);
            throw e;
        } finally {
            RequestInfoContextHolder.clear();
        }
    }

这样在整个线程中就可以直接RequestInfoContext requestInfoContext =  RequestInfoContextHolder.get();使用了

你可能感兴趣的:(springboot,java,jvm,开发语言)