我一直在阅读Tomcat中的“文章 on ThreadLocal in”一书。第一个示例包括以下代码:
public class MyCounter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class MyThreadLocal extends ThreadLocal<MyCounter> {
}
public class LeakingServlet extends HttpServlet {
private static MyThreadLocal myThreadLocal = new MyThreadLocal();
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
MyCounter counter = myThreadLocal.get();
if (counter == null) {
counter = new MyCounter();
myThreadLocal.set(counter);
}
response.getWriter().println(
"The current thread served this servlet " + counter.getCount()
+ " times");
counter.increment();
}
}它说所有的类都驻留在webapp中。然后概述了类加载器(不是ThreadLocal)泄漏的以下解释,我不明白这一点:
如果LeakingServlet至少被调用一次,并且服务它的线程没有停止,那么我们就创建了一个类加载器泄漏! 导致泄漏的原因是,我们有一个针对ThreadLocal实例的自定义类,以及一个绑定到线程的值的自定义类。实际上,重要的是这两个类都是由webapp类加载器加载的。
对ThreadLocal泄漏的解释是糟糕的。如果为请求提供服务的线程没有停止,那么如何才能发生ThreadLocal泄漏(实际上文章中说的是类加载程序泄漏)?这是否意味着,如果线程是Tomcat线程池的一部分,并且由于MyThreadLocal.remove()尚未关闭,那么MyCounter / MyThreadLocal的webapp类加载程序就不能被垃圾收集,因为线程被返回到池中?打电话给MyThreadLocal.remove()能解决这个问题吗?我不明白。
发布于 2017-12-23 02:08:07
解释是不正确的:
导致泄漏是因为我们为ThreadLocal实例提供了一个自定义类。
那部分是错的。线程类中的ThreadLocalMap使用weakReferences作为键,因此threadLocal实例是否是自定义类并不重要。我用我的自定义ThreadLocal类进行了测试,没有内存泄漏。
,也是绑定到线程的值的自定义类。
这是正确的。对于值,线程不使用弱引用,因此,如果值是一个自定义类,它将阻止垃圾收集其类加载器,这将导致该类加载器加载的所有类留在内存中,直到线程从线程池中删除为止。
https://stackoverflow.com/questions/47906166
复制相似问题