java.lang.OutOfMemoryError:无法创建新的本机线程

时间:2010-08-17 08:48:59

标签: java memory-leaks

我看到了这样的评论

  

我发现这个问题的一个地方就是如果你继续创建线程,而不是调用start(),直接在线程对象上调用run()。   这将导致线程对象无法解除引用...   所以有一段时间后,消息无法创建新的本机线程

Sun Java Forums

上的

在我的应用程序中,我们最初计划使用线程,但后来我们决定不再需要了,所以我们只调用run()而不是start()。我们是否需要为新的threadClass(..)做手动GC?

我的tomcat启动设置

-Xms1024m -Xmx1024m -XX:MaxPermSize=450m 

3 个答案:

答案 0 :(得分:11)

为什么首先要创建Thread

您的代码应该实现Runnable界面。

然后,当您决定要在一个线程中运行它时,简单地以Thread作为参数实例化Runnable并在start()上调用Thread对象

相反,如果您只是想在当前主题中运行它,只需在run()对象上调用Runnable即可。

这有几个好处:

  • 只要您不关心单独的线程,就不会涉及任何Thread个对象
  • 你的代码被包裹在一个Runnable中,它在概念上更接近:你不是在写一些特殊的线程,对吗?您只需编写一些可以执行/运行的代码。
  • 您可以轻松切换到使用进一步抽象决定的Executor

最后但并非最不重要的是,您避免了对是否创建本机线程资源的任何可能的混淆。

答案 1 :(得分:4)

调用run()方法时,不应创建新线程。当垃圾收集器未被引用时,您的对象将被收集。

您的其他代码部分可能会创建许多线程。

尝试在代码中使用ThreadPoolExecutor(线程池)来限制应用程序中的线程,并相应地调整线程池大小以获得更好的性能。

您还可以检查以下内容以调试您的问题:(从链接引用) 如果遇到此异常,有几件事要做。

  • 使用lsof -p PID命令(Unix 平台)看看有多少线程 这个过程很活跃。
  • 确定是否有最大值 每个进程定义的线程数 由操作系统。如果限制 对于应用来说太低了,试试吧 提高每个进程的线程限制。
  • 检查应用程序代码 确定是否有代码 创建线程或连接(例如 作为LDAP连接)而不是 摧毁他们。你可以转储 Java线程,看是否有 已创建过多的数字。
  • 如果您发现连接太多 由应用程序打开,制作 确定任何线程都可以 应用程序创建被破坏。一个 企业应用程序(.ear)或Web 应用程序(.war)在a下运行 长期运行的JVM。只是因为 申请完成并不意味着 JVM进程结束。它是 一个应用程序免费的命令 它分配的任何资源。 另一个解决方案是 应用程序使用线程池 管理所需的线程。

答案 2 :(得分:1)

此链接很好地描述了JVM如何抛出此错误: http://javaeesupportpatterns.blogspot.ro/2012/09/outofmemoryerror-unable-to-create-new.html

基本上它非常依赖于操作系统。在RedHat Linux 6.5(很可能是其他发行版/版本和内核版本)上,max_threads = max_process x 2。

最大线程数非常依赖于允许进程的数量。哪个进程的最大数量取决于您安装的最大物理内存。

如果您查看limits.conf文件(在我的RHL 6.5上,它位于/etc/security/limits.d/90-nproc.conf中)。执行文件:

# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.

*          soft    nproc     **1024**
root       soft    nproc     unlimited

您会看到非root用户的1024(这意味着最多2048个线程)。

要查看允许用户创建的最大线程数,请运行此命令" cat / proc / sys / kernel / threads-max"或" sysctl kernel.threads-max"。

要解决像这样的问题(至少它对我有用),你需要增加最大允许线程数:

echo 10000>的/ proc / SYS /内核/线程-MAX

这会影响所有用户和root用户。用户需要注销然后再次登录才能使设置生效。