如何从执行程序中“杀死”线程?

时间:2012-12-13 22:01:36

标签: java multithreading memory-leaks

我有一个tomcat webapp,我使用java执行器来执行一些runnables。

首先,我从执行程序实例中分配执行程序服务,如下所示:

executorService = Executors.newFixedThreadPool(nThreads, new MyThreadFactory(threadFactoryName))

然后,我使用执行程序服务启动任务:

executorService.execute(new MyRunnable);

然后,它似乎工作。但我的问题是,我正在追逐某种泄漏,在运行服务器一段时间后我得到了这个错误:

Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderCorePoolSize(ThreadPoolExecutor.java:703)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:652)
at something.server.ThreadExecutor.execute(MyRunnable.java:91)

我在tomcat实例上使用java VisualVM来跟踪线程分配。我看到当我调用'newFixedThreadPool'时,我看到'nThreads'新线程。但是在他们的工作完成后,我看到线程的状态是“等待”。

这是正常的吗?我不相信它,我知道runnables完成了他们的工作,但执行器服务永远不会释放线程。我可以做些什么来解放他们,还是我完全超出范围?

3 个答案:

答案 0 :(得分:4)

我认为您正在为每个请求实例化一个新的ExecutorService,或类似的东西。

在完成提交任务后,您应该只实例化一个ExecutorService并重复使用它,或者在服务上调用shutdown()shutdown函数将等待任务完成,然后释放线程。

答案 1 :(得分:2)

  

这是正常的吗?我不相信它,我知道runnables完成了他们的工作,但执行器服务永远不会释放线程。

是的,这很正常。实际上,这种行为是可取的,因为创建新线程是一项昂贵的操作。池线程(或至少是'核心'池线程)将继续存在,直到执行程序关闭。

  

我可以做些什么来解放他们,还是我完全超出范围?

您应该能够将线程池配置为具有较小的“核心”线程池和/或较小的keepAlive时间。有关详细信息,请参阅javadoc


  

问题是,我正在追逐某种泄漏,我在运行服务器一段时间后遇到此错误:

OOME不一定是泄漏的迹象。这可能表示您没有为您尝试创建的线程数留下足够的非堆内存。 (换句话说,你的线程池太大了。)

答案 2 :(得分:2)

您正在实例化修复的线程池。在您通过调用ExecutorServiceExecutorService终止ExecutorService.shutdown()之前,ExecutorService.shutdownNow()不会释放主题。