ThreadLocal引起的问题

来源:互联网 发布:caffe数据层参数 编辑:程序博客网 时间:2024/05/01 08:33

我们曾经做过一个多租户的项目,每个租户用一个唯一的平台号。程序中有的地方把当前用户的平台号放在一个ThreadLocal变量中。部署到tomcat上后发现一个很奇怪的现象:有时候用户的平台号会出现错乱,即一个人的平台号会出现在另一个登录用户的身上。最后发现问题出在线程池上。


大家知道ThreadLocal中的值实际上保存在线程对象中。在有线程池的情况下,线程用完后会还到线程池中,下一次需要线程时就从线程池中获取一个。如果ThreadLocal中的值上次没清空,这个值就会保留下来继续被使用。就是这个原因导致ThreadLocal中的数据混乱的。


原因清楚了,解决方法也就很简单了。ThreadLocal使用完后把值清除即可。


为简化问题,可以写一个ThreadLocalRegistry负责记住所有需要清除的ThreadLocal,然后在ThreadLocalCleanerInterceptor中统一清除。代码如下:

public class ThreadLocalRegistry {private static ThreadLocal<List<ThreadLocal>> threadLocals = new ThreadLocal<List<ThreadLocal>>();public static void register(ThreadLocal threadLocal) {synchronized (threadLocals) {if (threadLocals.get() == null) {threadLocals.set(new ArrayList<ThreadLocal>());}threadLocals.get().add(threadLocal);}}public static void clear() {synchronized (threadLocals) {if (threadLocals.get() == null) {return;}for (ThreadLocal threadLocal : threadLocals.get()) {threadLocal.remove();}threadLocals.get().clear();threadLocals.remove();Guzz.setDBGroup(null);Guzz.setTableCondition(null);}}}

public class ThreadLocalCleanerInterceptor implements Filter {public void destroy() {}public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {try {chain.doFilter(req, res);} finally {ThreadLocalRegistry.clear();}}public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {try {chain.doFilter(request, response);} finally {ThreadLocalRegistry.clear();}}@Overridepublic void init(FilterConfig config) throws ServletException {}}




0 0
原创粉丝点击