# introduce

自 JDK1.2 版本起,Java 就提供了 java.lang.ThreadLocal, ThreadLocal 为每一个使用该变量的线程都提供了独立的副本,可以做到线程间的数据隔离,每一个线程都可以范文各自内部的副本变量。

小贴士

ThreadLocal 并不是解决多线程下共享资源的技术,一般情况下,每一个线程的 ThreadLocal 存储的都是 new 的全新的对象。

ThreadLocal 分析文章

# 实现

开发运行项目中的上下文传递,如:用户上下文传递

/**
 * <p> 微信用户信息上下文 :ThreadLocal 存储 </p>
 *
 */
public class WxUserContextHandler {
	public static ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>();

	public static void set(String key, Object value) {
		Map<String, Object> map = threadLocal.get();
		if (map == null) {
			map = new HashMap<>();
			threadLocal.set(map);
		}
		map.put(key, value);
	}

	public static Object get(String key) {
		Map<String, Object> map = threadLocal.get();
		if (map == null) {
			map = new HashMap<>();
			threadLocal.set(map);
		}
		return map.get(key);
	}
	
	public static Long getUserId() {
		Object value = get(IConstants.WX_USER_ID_KEY);
		return value == null ? null : (Long) value;
	}
	
	public static void setUserId(Long userId) {
		set(IConstants.WX_USER_ID_KEY, userId);
	}

}

在 Spring 为框架的项目开发中需要在 HandlerInterceptorAdapter#afterCompletion 中清除 ThreadLocal 信息,

Spring 处理的线程都是从线程池中获取,会存在脏数据的问题

代码如下

public class WxserAuthInterceptor extends HandlerInterceptorAdapter {
	......
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        WxUserContextHandler.threadLocal.remove();
        super.afterCompletion(request, response, handler, ex);
    }
}
精彩内容推送,请关注公众号!
最近更新时间: 5/14/2020, 12:49:41 PM