Hi, folks:
我在跑一个模拟程序的时候, 报出OOM: unable to create new native thread的错误.
机器:
MAC OSX, 2 * 2.8GHz Quad-Core Interl Xeon Duo;
10GB 800MHz DDR2 FB-DIMM
SUN JVM 1.6程序参数:
-server -d64 -XX:+UseParallelGC -Xms2g -Xmx4g 我觉得机器和程序参数设置的内存支持都是应该是没问题的, 通过jconsole观察, 发现崩溃时其实内存使用量并不是很高, 大约在1.2~1.5G之前, 但是线程的创建量已经到了约2500. 自己判断, 这应该不是内存不够, 而是线程量创建过大. 不知道是否正确.如果是的话, 请问能否在jvm里面修改参数已支持更高的线程量, 一般来说最大线程量会有什么限制.谢谢! Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:615)
at eduni.simjava.Sim_system.run_start(Sim_system.java:922)
at eduni.simjava.Sim_system.run(Sim_system.java:1744)
at gridsim.GridSim.startGridSimulation(GridSim.java:602)
at ch.eif.gridgroup.magate.MaGateTrunk.simpleScenario(MaGateTrunk.java:227)
at ch.eif.gridgroup.magate.MaGateTrunk.main(MaGateTrunk.java:118)
Exception in thread "Thread-1" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:615)
at ch.eif.gridgroup.magate.em.ssl.Server.fetchAndExecuteMessage(Server.java:63)
at ch.eif.gridgroup.magate.em.ssl.Server.run(Server.java:50)
at java.lang.Thread.run(Thread.java:637)
set JAVA_OPTS=%JAVA_OPTS% -Xms128m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m set JAVA_OPTS=%JAVA_OPTS% -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
简直高到搞笑了,竟然还想要调高线程数。我不知道你要这么多线程干什么,可以说任何程序都不需要这么多线程,再大的任务应该用线程池来处理。
如果线程数超过CPU数*20,那101%是设计错误。你的线程数已经2500.
2500/20,你的服务器有125个CPU?
创建一个线程,需要1G左右的内核栈和用户栈。用来保存模式切换时的当前状态。你有多少内存?
另外太多的线程之间切换的开销会比做实际工作还要多。比如你实际的工作只要100M内存,30秒完成了,但因为线程太多。要管理它们之间和调度和线程结象本身却要花1G内存和100秒的时间。
在目前的顶级硬件机器上超过100个线程,设计就有问题了。不管你任务有多少,应该把任务加到一个队列,然后多个线程分别从这个队列中取任务执行,一个线程执行一次后再取再执行,循环利用已经存在线程。
创建一个线程,需要1G左右的内核栈和用户栈。用来保存模式切换时的当前状态。你有多少内存?
另外太多的线程之间切换的开销会比做实际工作还要多。比如你实际的工作只要100M内存,30秒完成了,但因为线程太多。要管理它们之间和调度和线程结象本身却要花1G内存和100秒的时间。
在目前的顶级硬件机器上超过100个线程,设计就有问题了。不管你任务有多少,应该把任务加到一个队列,然后多个线程分别从这个队列中取任务执行,一个线程执行一次后再取再执行,循环利用已经存在线程。
建议改变一下算法,减少线程数
设置一下set JAVA_OPTS=%JAVA_OPTS% -Xms128m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256mset JAVA_OPTS=%JAVA_OPTS% -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
肯能会管用些 但是不会太有用
简要回复一下:
是的, 线程确实多的过了, 因为模拟程序里面采用了一个第三方包GridSim来模拟基础的网格行为(grid computing), 有大量的线程被这个基础包创建出来模拟job, resource, log等等事件.
这确实是一个瓶颈, 但不是"搞笑的设计", 任何机器都不可能无上限的跑出所有规模的模拟场景, 所以这里我希望寻找一台机器能达到的最大规模能有多少.
我现在比较困惑的是, 这个线程的极限, 是针对整个机器而言的, 还是针对单个jvm而言的. 如果是针对单个jvm的话, 或许在同一台机器里同时运行多个主程序会是个选择, 否则就只有rmi到多台机器了, 而这里又涉及到rmi的通讯延迟会有多少的问题.