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

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

最近,在使用Java的ThreadPoolExecutor来实现一个并发功能的时候,发现程序刚执行起来不久,就提示了错误:

1

OutOfMemoryError: unable to create new native thread

并且服务器立即陷入类似于“无响应”的状态,无法用Ctrl+C结束掉我的Java程序,按Ctrl+C的时候,命令行只是不断地打印出类似于下面的消息:

1

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系统的设置值:

1

ulimit -a

其输出类似于:

扫描二维码关注公众号,回复: 6754744 查看本文章

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

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的代码,当我们创建一个对象的时候,会使用如下的构造函数:

1

2

3

4

5

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 文件,其内容类似于:

1

2

3

4

5

6

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

猜你喜欢

转载自blog.csdn.net/hellozhxy/article/details/91995718