如何终止Java中容器创建的线程
我正在ApacheTomcat6上运行一个多线程Java web应用程序。而不是使用如何终止Java中容器创建的线程,java,multithreading,Java,Multithreading,我正在ApacheTomcat6上运行一个多线程Java web应用程序。而不是使用新线程()反模式,我将线程实例化留给Tomcat(参见下面的代码) 在过去的几天里,我注意到web应用程序变得越来越慢。重启servlet容器后,一切都恢复正常 由于我在处理线程后没有终止线程(不知道是否必须终止线程,或者垃圾收集器是否会销毁线程),因此我猜测这是性能损失的原因 代码基本上如下所示: 自定义服务器侦听器(我将其添加到web.xml中): 线程实例化: for (Object foo : bar){
新线程()代码>反模式,我将线程实例化留给Tomcat(参见下面的代码)
在过去的几天里,我注意到web应用程序变得越来越慢。重启servlet容器后,一切都恢复正常
由于我在处理线程后没有终止线程(不知道是否必须终止线程,或者垃圾收集器是否会销毁线程),因此我猜测这是性能损失的原因
代码基本上如下所示:
自定义服务器侦听器(我将其添加到web.xml中):
线程实例化:
for (Object foo : bar){
MyTaskRunner.EXECUTOR_SERVICE.submit(new Runnable() {
public void run() {
doSomethingWith(foo);
});
}
那么,在run()
完成之后,我有什么特别的事情要做吗?您是否正确地在web.xml中注册了上下文侦听器
你的跑步方法会在某个时刻结束吗?还是他们一直在无限期地奔跑
ExecutorSerfice将简单地调用Thread.start。对于您来说,您仍然在从Web应用程序内部启动线程,只要您正确地关闭线程,这并不是一件可怕的事情。无论您使用什么技术,run()方法的执行都不会被截断。您是否在web.xml中正确注册了上下文侦听器
你的跑步方法会在某个时刻结束吗?还是他们一直在无限期地奔跑
ExecutorSerfice将简单地调用Thread.start。对于您来说,您仍然在从Web应用程序内部启动线程,只要您正确地关闭线程,这并不是一件可怕的事情。无论使用何种技术,run()方法的执行都不会被截断。有关线程和GC的一些基本事实:
- 线程运行时,不会对其进行垃圾收集
- 当线程终止时,其堆栈将被删除,其
thread
对象将从ThreadGroup
数据结构中删除。线程的其余状态受正常可达性规则的约束
- 您不需要做任何特殊的事情来使线程终止。它发生在
run
方法调用结束时,原因可能是它返回了,也可能是因为它退出时出现了(未捕获的)异常
现在谈谈你的特殊问题。许多因素可能会导致性能下降。例如:
- 您的一些线程可能会卡住;e、 g.等待一个锁,等待一个不会到达的通知,或者只是卡在一个无限的CPU循环中
- 您可能有太多的线程在运行(做有用的或半有用的事情),而速度减慢可能是锁争用、CPU资源不足或抖动的结果
- 您可能会有某种内存泄漏,并且速度减慢可能是应用程序开始耗尽堆空间的征兆
要了解发生了什么,您需要进行一些性能监视:
- 查看操作系统级别的统计信息,看看应用程序是否在颠簸
- 使用内存配置文件查看应用程序是否内存不足。如果是,请查看是否存在内存泄漏,并进行跟踪
- 使用性能分析器查看是否存在特定的热点,或者是否存在大量锁争用
我同意这一评论。线程池大小为10000的线程池非常大。它应该是一个小常数乘以应用程序可用的内核数。关于线程和GC的一些基本事实:
- 线程运行时,不会对其进行垃圾收集
- 当线程终止时,其堆栈将被删除,其
thread
对象将从ThreadGroup
数据结构中删除。线程的其余状态受正常可达性规则的约束
- 您不需要做任何特殊的事情来使线程终止。它发生在
run
方法调用结束时,原因可能是它返回了,也可能是因为它退出时出现了(未捕获的)异常
现在谈谈你的特殊问题。许多因素可能会导致性能下降。例如:
- 您的一些线程可能会卡住;e、 g.等待一个锁,等待一个不会到达的通知,或者只是卡在一个无限的CPU循环中
- 您可能有太多的线程在运行(做有用的或半有用的事情),而速度减慢可能是锁争用、CPU资源不足或抖动的结果
- 您可能会有某种内存泄漏,并且速度减慢可能是应用程序开始耗尽堆空间的征兆
要了解发生了什么,您需要进行一些性能监视:
- 查看操作系统级别的统计信息,看看应用程序是否在颠簸
- 使用内存配置文件查看应用程序是否内存不足。如果是,请查看是否存在内存泄漏,并进行跟踪
- 使用性能分析器查看是否存在特定的热点,或者是否存在大量锁争用
我同意这一评论。线程池大小为10000的线程池非常大。它应该是一个小常数乘以应用程序可用的内核数
新线程();反模式
你们从哪里知道这是反模式的
无论如何,10000个线程太多了。每个线程都会占用内存,操作系统也有其自身的限制,因此,作为一种安全的路径,尽量不要超过几千个线程
连接jconsole(jstack可能就足够了)来查看线程正在做什么——不管它们是在睡觉还是在等待什么
而且不是Tomcat在管理th
for (Object foo : bar){
MyTaskRunner.EXECUTOR_SERVICE.submit(new Runnable() {
public void run() {
doSomethingWith(foo);
});
}