如何终止Java中容器创建的线程

如何终止Java中容器创建的线程,java,multithreading,Java,Multithreading,我正在ApacheTomcat6上运行一个多线程Java web应用程序。而不是使用新线程()反模式,我将线程实例化留给Tomcat(参见下面的代码) 在过去的几天里,我注意到web应用程序变得越来越慢。重启servlet容器后,一切都恢复正常 由于我在处理线程后没有终止线程(不知道是否必须终止线程,或者垃圾收集器是否会销毁线程),因此我猜测这是性能损失的原因 代码基本上如下所示: 自定义服务器侦听器(我将其添加到web.xml中): 线程实例化: for (Object foo : bar){

我正在ApacheTomcat6上运行一个多线程Java web应用程序。而不是使用
新线程()反模式,我将线程实例化留给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);
    });
}