最近,在使用Java的ThreadPoolExecutor来实现一个并发功能的时候,发现程序刚执行起来不久,就提示了错误:
OutOfMemoryError: unable to create new native thread
并且服务器立即陷入类似于“无响应”的状态,无法用Ctrl+C结束掉我的Java程序,按Ctrl+C的时候,命令行只是不断地打印出类似于下面的消息:
Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated
在其他已经连上的terminal下,我想尝试用 ps -ef | grep xxx 来找出进程的pid并kill掉它,也无果,因为只要输完ps命令,再一回车,马上就提示错误(大概意思就是资源不足),于是在不重启系统的情况下,只能静静等待,直到Linux系统恢复了响应,就可以用ps -ef查出其pid并kill掉它了。
文章来源:http://www.codelast.com/
但是为嘛会出现这样的问题?
首先,服务器内存是非常充足的,不应该是内存真的不够用;其次,我仔细检查了一遍我的代码,也并无异常之处;再次,我的程序也不会占用非常大的内存。
于是我问了一下Google,找到了原因所在:我程序中设置的ThreadPoolExecutor并发数超出了系统限制。这个限制,就是所谓的“max user processes”限制,可以用如下命令查看Linux系统的设置值:
ulimit -a
其输出类似于:
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 385903 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 65535 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 1024 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
看到“max user processes”那一行了吗?1024就是我当前用户的最大允许值,当超过这个值的时候,就无法创建新的process了。
文章来源:http://www.codelast.com/
对应到使用ThreadPoolExecutor的代码,当我们创建一个对象的时候,会使用如下的构造函数:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { //... }
其中,第1和第2个参数,就是线程池里线程数的大小:
@param corePoolSize the number of threads to keep in the pool, even if they are idle.@param maximumPoolSize the maximum number of threads to allow in the pool.
虽然我只把这两个数值分别设置成了400和500,但是由于我的用户下还运行有其他很多程序,因此,它们加在一起占用的线程数超过了1024的时候,就会出现前面的错误。
文章来源:http://www.codelast.com/
要修改Linux系统中的这个限制,可以修改 /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
把里面的数值改掉即可。
由于不方便修改Linux系统配置,因此,我把ThreadPoolExecutor的线程数调小到100,发现程序运行起来再也没有出现过上面的问题,非常稳定。
文章来源:https://www.codelast.com/
➤➤ 版权声明 ➤➤
转载需注明出处:codelast.com
感谢关注我的微信公众号(微信扫一扫):
大兄弟,你的站点不爬梯子访问不了哇。
上海电信,可无障碍访问