【发布时间】:2011-01-08 04:37:55
【问题描述】:
传统智慧告诉我们,大容量企业 Java 应用程序应优先使用线程池,而不是生成新的工作线程。使用java.util.concurrent 让这一切变得简单。
但是,确实存在不适合线程池的情况。我目前正在努力解决的具体示例是使用InheritableThreadLocal,它允许ThreadLocal 变量被“传递”到任何产生的线程。这种机制在使用线程池时会中断,因为工作线程通常不是从请求线程产生的,而是预先存在的。
现在有一些方法可以解决这个问题(可以显式传入线程局部变量),但这并不总是合适或实用的。最简单的解决方案是按需生成新的工作线程,并让InheritableThreadLocal 完成它的工作。
这让我们回到了问题 - 如果我有一个大容量站点,其中用户请求线程每个都产生六个工作线程(即不使用线程池),这会给 JVM 带来问题吗?我们可能会谈论每秒创建几百个新线程,每个线程持续时间不到一秒。现代 JVM 是否对此进行了很好的优化?我记得在 Java 中需要对象池的日子,因为创建对象的成本很高。从那以后,这变得不必要了。我想知道这是否同样适用于线程池。
如果我知道要衡量什么,我会对其进行基准测试,但我担心问题可能比使用分析器衡量的更为微妙。
注意:使用线程局部变量的智慧不是这里的问题,所以请不要建议我不要使用它们。
【问题讨论】:
-
我打算建议将您的 ThreadLocal 包装在访问器方法中可能会解决您使用 InheritableThreadLocal 的问题,但您似乎不想听到这个。另外,您似乎将 InheritableThreadLocal 用作带外调用框架,老实说,这似乎是一种代码味道。
-
就线程池而言,主要好处是控制:您知道您不会突然尝试在一秒钟内启动 10,000 个线程。
-
@kdgregory:对于您的第一点,有问题的 ThreadLocals 由 Spring 的 bean 作用域使用。这就是 Spring 的工作方式,而不是我可以控制的东西。对于您的第二点,入站请求线程受tomcat的线程池限制,因此限制是固有的。
-
Tomcat线程池如何限制你创建的线程数?您描述了一个应用程序,其中“用户请求线程 [spawn] 六个工作线程”,我认为您关心的是这些线程。一个错误,您可以轻松地为单个请求启动 10,000 个线程。
-
然而,关于您需要 ThreadLocal 的原因:它是有效的,并且在消息中发布以避免聪明的 cmets 是一件好事 :-)
标签: java performance multithreading