Java并发之ThreadLocal理解

Java并发之ThreadLocal理解

  • 介绍
  • 使用场景

介绍

ThreadLocal是为实现对资源对象的线程隔离,使每个线程拥有自己的资源,避免并发时争用引发线程安全问题
实现原理: 主要是其内部存在一个ThreadLocalMap存储资源,将ThreadLocal对象自己为key,资源对象作为value,get方法获取,set存储,remove方法移除。
注:

  1. 添加时发生哈希冲突,使用开放寻址法解决,即从冲突位置向后寻找空闲位置插入
  2. ThreadLocalMap在垃圾回收时key是弱引用可以被回收但value是强引用,及时不再被引用也无法被垃圾回收,长期累加会导致内存泄露问题,所有在使用时应在对象使用完成后调用remove方法手动清除

使用场景

ThreadLocal可用来存储登录用户状态,即用户登录后将从前端请求获取的token解析出用户信息存储到ThreadLocal中,在业务层等使用时实现对用户状态的快速获取。请求结束时,调用remove方法清除
例子
ThreadLocal工具类

public class BaseContext {
    private static ThreadLocal<MemberInfoDto> threadLocal = new ThreadLocal<>();

    //作用在同一线程范围内
    public static void setMember(MemberInfoDto memberLogin){
        threadLocal.set(memberLogin);
    }

    public static MemberInfoDto getMember(){
        return threadLocal.get();
    }

    public static void removeMember(){threadLocal.remove();}
}

在请求拦截器中获取token解析存入ThreadLocal

		...
		int status = AppJwtUtil.checkTokenTime(claims);
        if (status == 1 || status == 2) {
            BaseContext.setMember(new MemberInfoDto(
                    (Long) claims.get("id"),
                    (int) claims.get("flag")));
            return true;
        } else {
            response.setStatus(401);
            response.getWriter().print("无权限访问!");
            return false;
        }
        ...

在业务层获取使用
(通过ThreadLcoalMap存储的登录用户信息,判断该请求是否有权限调用该方法)

public ResponseResult getMemberList(String direction) {

        if (BaseContext.getMember().getFlag() != 1) {
            return ResponseResult.errorResult(500, "缺少权限");
        }
        List<MemberListDto> memberListDtos;
        if (StrUtil.isBlank(direction)) {
            memberListDtos = oaMemberMapper.getMemberList();
        } else {
            memberListDtos = oaMemberMapper.getMemberListWithDirection(direction);
        }
        return ResponseResult.okResult(memberListDtos);
    }

请求完成时销毁

@Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        BaseContext.removeMember();
    }

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