在近日的测试中发现,无论resin.conf中配置的并发连接数多高,例如2048,resin实例能支持的并发活动线程数,或者说是活动连接数,最高只能去到500多。
linux下使用以下命令查看:ps -eLf |grep |wc -l
// default timeout
private long _timeout = 65000L;
private int _connectionMax = 512;//查找resin所有源码后,发现没有对这个值进行设置
private int _minSpareConnection = 16;
private int _keepaliveMax = -1;
private int _minSpareListen = 5;
private int _maxSpareListen = 10;
这个加大以后能到3000
<thread-pool>
<!-- Maximum number of threads. -->
<thread-max>20480</thread-max>
<!-- Minimum number of spare connection threads. -->
<spare-thread-min>10</spare-thread-min>
</thread-pool>
然后就会报这个错误
java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:574)
at com.caucho.util.ThreadPool$ThreadLauncher.startConnection(ThreadPool.java:621)
at com.caucho.util.ThreadPool$ThreadLauncher.run(ThreadPool.java:660)
这个限制可以换64位系统解决:
这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一个进程的最大内存
JVMMemory JVM内存
ReservedOsMemory 保留的操作系统内存
ThreadStackSize 线程栈的大小
在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
结合上面例子我们来对公式说明一下:
MaxProcessMemory 在32位的 windows下是 2G
JVMMemory eclipse默认启动的程序内存是64M
ReservedOsMemory 一般是150M左右
ThreadStackSize 32位 JDK 1.5默认的stacksize 256K左右
公式如下:
(2*1024*1024-64*1024-150*1024)/256 = 7336
公式计算所得7336,和实践7117基本一致(有偏差是因为ReservedOsMemory不能很精确)
由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。
咦,有点背我们的常理,恩,让我们来验证一下,依旧使用上面的测试程序,加上下面的JVM参数,测试结果如下:
ThreadStackSize JVMMemory 能创建的线程数
默认的256K -Xms64m -Xmx64m i = 7117
默认的256K -Xms32m -Xmx32m i = 7244
-Xss128k -Xms64m -Xmx64m i = ?
完全和公式一致。
三、解决问题:
1, 如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。
2, 如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:
a, MaxProcessMemory 使用64位操作系统
b, JVMMemory 减少JVMMemory的分配
c, ThreadStackSize 减小单个线程的栈大小
分享到:
相关推荐
通过修改`server.xml`,我们可以调整服务器的监听端口、最大线程数、连接超时时间以及重定向端口,以优化服务器性能。例如,将`port`设置为8080可以改变默认的HTTP端口,`maxThreads`控制并发处理能力,`connection...
熟悉WebLogic、JBoss等应用服务器的安装、配置和管理,支持高可用性和负载均衡。 #### 19. 面向切面编程(AOP) 学习AOP概念,掌握AspectJ或AspectWerkz等工具,实现代码的横切关注点分离。 #### 20. 日志、调度与...
学习如何使用Tomcat、Resin、JRun等Web服务器进行应用的部署与管理。 ### 10. 远程方法调用(RMI) 掌握远程API,如RMI(Remote Method Invocation)和RMI/IIOP(Internet Inter-ORB Protocol)等,实现分布式系统...
- JDBC (Java Database Connectivity): 数据库连接技术。 - JNDI (Java Naming and Directory Interface): 名称和服务定位服务。 - JPA (Java Persistence API): 对象关系映射(ORM)标准。 - JMS (Java Message ...
学习如何使用WebLogic、JBoss等企业级应用服务器,以及它们的特性与配置,可以提高你构建复杂应用的能力。 #### 13. 面向切面编程与工具 熟悉面向切面编程(AOP)及其工具如AspectJ、AspectWerkz,可以帮助你更...
- **Tomcat、Resin等**:掌握常见的应用服务器部署与配置方法。 - **Web应用管理**:学习如何部署、启动、停止Web应用。 ### 10. 远程调用 - **RMI/RMI-IIOP**:理解远程方法调用机制,实现分布式应用。 - **CORBA*...
- **位运算方法**:利用位与运算判断一个数是否为2的幂次方。例如,若x为2的幂次方,则`x & (x - 1)`的结果为0。 - **数学方法**:通过对数函数计算,如`log2(x)`为整数则x是2的幂次方。 #### 数据结构:自联表与...
- WebLogic、JBoss等应用服务器的部署和配置,以及集群和负载均衡策略。 #### 23. **面向切面编程(AOP)** - 使用AspectJ、AspectWerkz等框架增强代码,实现日志记录、事务管理等横切关注点。 #### 24. **日志...