【问题标题】:Remove ThreadLocal object within a Spring MVC website?在 Spring MVC 网站中删除 ThreadLocal 对象?
【发布时间】:2016-09-18 09:53:00
【问题描述】:

我有以下课程:

public class AppContext {

    private static final ThreadLocal<AppContextData> contextHolder = new ThreadLocal<AppContextData>() {

        @Override
        protected AppContextData initialValue() {
            return new AppContextData();
        }
    };

    public static AppContextData get() {
        return contextHolder.get();
    }

    public static void unset() {
        contextHolder.remove();
    }
}

public class AppContextData {
   //many getter and setter methods
}

网站开始在拦截器中使用 ThreadLocal 对象,并在整个网络请求中使用该对象。

public class MyIntercepter extends HandlerInterceptorAdapter {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  {

        AppContext.get();
        //..... 
    }
}

我在 Tomcat 8.x 上运行这个网站,我发现日志有以下错误消息。

我该如何解决这个问题?

非常感谢您的任何意见!

20-May-2016 22:43:53.657 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks Web 应用程序 [ROOT] 创建了一个 ThreadLocal,其键类型为 [my.organization. data.AppContext$1](值 [my.organization.data.AppContext$1@31d4463a])和类型为 [my.organization.data.AppContextData] 的值(值 [my.organization.data.AppContextData@e89d5f4])但失败在 Web 应用程序停止时将其删除。线程将随着时间的推移而更新,以避免可能的内存泄漏。

【问题讨论】:

  • 确保 AppContext.unset() 被调用。 Tomcat 希望您明确删除 ThreadLocal。

标签: java spring-mvc thread-local


【解决方案1】:

JanPi 已经在 cmets 中说明了我们必须做什么。如果有人想知道如何,这里是:

public class MyIntercepter extends HandlerInterceptorAdapter {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  {
        AppContext.get();
        //..... 
    }

    public void afterCompletion(
        HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        AppContext.unset();
    }

    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        // only relevant when a handler starts an asynchronous request.
        AppContext.unset();
    }
}

postHandle 方法看起来不错,但 afterCompletion 更好,因为即使处理程序未能正确处理请求(也就是发生异常),它也会被调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多