是否值得在 Filter 中清理 ThreadLocals 以解决与线程池相关的问题?
Posted
技术标签:
【中文标题】是否值得在 Filter 中清理 ThreadLocals 以解决与线程池相关的问题?【英文标题】:Is it worth cleaning ThreadLocals in Filter to solve thread pool-related issues? 【发布时间】:2011-06-30 13:39:19 【问题描述】:简而言之 - tomcat 使用线程池,因此线程被重用。一些库使用ThreadLocal
变量,但不清理它们(使用.remove()
),所以实际上它们将“脏”线程返回到池中。
Tomcat 具有在关闭时检测这些东西并清理线程本地变量的新功能。但这意味着线程在整个执行过程中都是“脏的”。
我能做的是实现一个Filter
,在请求完成后(线程返回到池中),清理所有ThreadLocal
s,使用code from tomcat(那里的方法称为@ 987654326@).
问题是,值得吗?两个优点:
防止内存泄漏 防止库的不确定行为,假设线程是“新的”一个缺点:
该解决方案使用反射,因此可能会很慢。当然,所有反射数据 (Field
s) 都会被缓存,但仍然如此。
另一种选择是将问题报告给不清理其线程本地变量的库。
【问题讨论】:
【参考方案1】:我会通过向库开发人员报告问题的途径,原因有两个:
这将有助于其他想要使用相同库但缺乏技能/时间来发现这种可怕的内存泄漏的人。 帮助库的开发人员构建更好的产品。老实说,我以前从未见过这种类型的错误,我认为这是一个例外,而不是我们应该注意的事情,因为它经常发生。你能分享一下你在哪个图书馆看到过这种行为吗?
附带说明,如果仍然附加了 ThreadLocal 变量,我不介意在开发/测试环境中启用该过滤器并记录严重错误。
【讨论】:
这不仅仅是一个库,这就是问题所在。清理线程局部变量似乎很少进行。 未能清理 ThreadLocal 通常不是内存泄漏 - 例如,如果您使用 ThreadLocal理论上,这似乎是个好主意。但是,我可以看到您可能不想要这样做的一些情况。例如,一些与 xml 相关的技术有一些重要的设置成本(如设置 DocumentBuilders 和 Transformers)。如果你在你的 web 应用程序中做了很多 很多,那么将这些实例缓存在 ThreadLocals 中可能是有意义的(因为这些实用程序通常不是线程安全的)。在这种情况下,您可能不想在请求之间清除这些内容。
【讨论】:
即使有一些副作用,我认为也不应该那样滥用。 @Bozho,你为什么认为这是一种滥用?它更像是一个廉价的对象池。 因为您永远无法确定给定的库是否能正确执行所有操作。安全总比后悔好;)【参考方案3】:如果您认为线程的脏污实际上可能会导致问题,那么这是明智的做法。尽可能避免问题。
使用 threadlocals 可能是库的不良行为,您当然应该向作者报告,但遗憾的是,现在,由您来处理它。
我不会太担心性能。反射的慢一点是元数据查找;一旦你有一个 Field 对象,然后使用它会相当快,并且随着时间的推移变得更快 - AIUI,它通过对 JVM 进行本机调用开始工作,但在使用了一些次数后,它会生成用于访问的字节码,这然后可以编译为本机代码,优化,内联等,因此它不应该比直接字段访问慢很多。不过,我认为 Tomcat 代码不会跨请求重用 Field 对象,所以如果你想利用它,你必须编写自己的清理代码。无论如何,性能成本将远远小于与请求相关的 IO 成本。
【讨论】:
以上是关于是否值得在 Filter 中清理 ThreadLocals 以解决与线程池相关的问题?的主要内容,如果未能解决你的问题,请参考以下文章