转载请注明出处:http://www.codelast.com/

最近,在使用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,发现程序运行起来再也没有出现过上面的问题,非常稳定。

[原创] 使用ThreadPoolExecutor产生的 OutOfMemoryError: unable to create new native thread 错误

发表评论

电子邮件地址不会被公开。 必填项已用*标注