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)

解决方案 »

  1.   

    虽然不知道是什么问题,但是把我们服务器上设定的几个个人觉得比较重要的参数给你看一下
    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 
      

  2.   

    你这个不是内存的原因,是程序的原因.仔细检查程序中是否连接数据库后,没有释放连接.或者IO操作后,没有关闭IO,等等情况
      

  3.   

    绝对是线程数太多。
    简直高到搞笑了,竟然还想要调高线程数。我不知道你要这么多线程干什么,可以说任何程序都不需要这么多线程,再大的任务应该用线程池来处理。
    如果线程数超过CPU数*20,那101%是设计错误。你的线程数已经2500.
    2500/20,你的服务器有125个CPU?
    创建一个线程,需要1G左右的内核栈和用户栈。用来保存模式切换时的当前状态。你有多少内存?
    另外太多的线程之间切换的开销会比做实际工作还要多。比如你实际的工作只要100M内存,30秒完成了,但因为线程太多。要管理它们之间和调度和线程结象本身却要花1G内存和100秒的时间。
    在目前的顶级硬件机器上超过100个线程,设计就有问题了。不管你任务有多少,应该把任务加到一个队列,然后多个线程分别从这个队列中取任务执行,一个线程执行一次后再取再执行,循环利用已经存在线程。
      

  4.   

    本帖最后由 java2000_net 于 2009-03-07 15:27:07 编辑
      

  5.   

    是线程数太多。这么多线程,再大的任务应该用线程池来处理。如果线程数超过CPU数*20,那101%是设计错误。你的线程数已经2500.远远超出了这个标准,
    创建一个线程,需要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 
    肯能会管用些 但是不会太有用
      

  6.   

    非常感谢诸位的回复, 最近几天在赶两篇论文, 回复有点延迟, 等搞定后再回头试验一下.
    简要回复一下:
    是的, 线程确实多的过了, 因为模拟程序里面采用了一个第三方包GridSim来模拟基础的网格行为(grid computing), 有大量的线程被这个基础包创建出来模拟job, resource, log等等事件. 
    这确实是一个瓶颈, 但不是"搞笑的设计", 任何机器都不可能无上限的跑出所有规模的模拟场景, 所以这里我希望寻找一台机器能达到的最大规模能有多少.
    我现在比较困惑的是, 这个线程的极限, 是针对整个机器而言的, 还是针对单个jvm而言的. 如果是针对单个jvm的话, 或许在同一台机器里同时运行多个主程序会是个选择, 否则就只有rmi到多台机器了, 而这里又涉及到rmi的通讯延迟会有多少的问题.