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

我看到这样的评论

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

在Sun Java论坛上

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

我的tomcat启动设置

-Xms1024m -Xmx1024m -XX:MaxPermSize=450m 

为什么要首先创建一个Thread

您的代码应该实现Runnable接口。

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

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

这有几个好处:

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

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

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

您的其他代码部分可能会创建很multithreading。

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

您还可以检查以下内容以调试您的问题:(从链接引用)如果遇到此exception,可以执行以下操作。

  • 使用lsof -p PID命令(Unix平台)查看此进程有多少活动线程。
  • 确定操作系统定义的每个进程是否存在最大线程数。 如果应用程序的限制太低,请尝试提高每进程的线程限制。
  • 检查应用程序代码以确定是否存在创建线程或连接(例如LDAP连接)而不销毁它们的代码。 您可以转储Java线程以查看是否已创建过多的数字。
  • 如果发现应用程序打开的连接太多,请确保销毁应用程序创建的任何线程。 企业应用程序(.ear)或Web应用程序(.war)在长时间运行的JVM下运行。 仅仅因为应用程序已完成并不意味着JVM进程结束。 应用程序必须释放它分配的任何资源。 另一种解决方案是应用程序使用线程池来管理所需的线程。

此链接很好地描述了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”。

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

echo 10000> / proc / sys / kernel / threads-max

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