java ThreadPoolExecutor 无法创建本机线程
java ThreadPoolExecutor can't create a native thread
我的系统需要一个全局线程池来处理客户的订单。该系统基于 tomcat 并且应该 24/7 全天候接受客户的请求。我像这样使用 ThreadPoolExecutor:
private ThreadPoolExecutor exec = new ThreadPoolExecutor(100, 1000, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
但有时我的系统挂出异常:'OutOfMemory: Cannot create a new native thread'。所以问题是:
1. 所有提交的线程会一直驻留在池中直到关闭吗?
2. 我应该用什么来创建一个可以重用或清理已完成任务的线程池,这样它就永远不会挂起?
我还在pool.submit之前添加了一条日志信息:
logger.info("Active count: "+pool.getActiveCount()+" completed: "+pool.getCompletedTaskCount());
但活动计数始终为零。为什么? java 版本是 FreeBSD 上的 openJDK 8
太多的事情可能会出错,最明显的是:
maximumPoolSize
设置为 1000,这是一个幻数,与程序 运行 所在的硬件无关。
Back-pressure
,您使用 LinkedBlockingQueue
来欢迎任何新任务,您可能需要考虑使用 ArrayBlockingQueue
并给它一个 capacity
。
配置 maximumPoolSize
取决于您的应用程序,您的任务是 compute bound
?然后,池大小大于生产机器(而非开发机器)上可用内核的数量不会给你带来任何好处,而是为上下文切换和内存消耗的开销付出代价。
Java中有一个非常有用的方法可以获取你拥有的核心数,请使用它。
Runtime.getRuntime().availableProcessors();
我的系统需要一个全局线程池来处理客户的订单。该系统基于 tomcat 并且应该 24/7 全天候接受客户的请求。我像这样使用 ThreadPoolExecutor:
private ThreadPoolExecutor exec = new ThreadPoolExecutor(100, 1000, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
但有时我的系统挂出异常:'OutOfMemory: Cannot create a new native thread'。所以问题是: 1. 所有提交的线程会一直驻留在池中直到关闭吗? 2. 我应该用什么来创建一个可以重用或清理已完成任务的线程池,这样它就永远不会挂起?
我还在pool.submit之前添加了一条日志信息:
logger.info("Active count: "+pool.getActiveCount()+" completed: "+pool.getCompletedTaskCount());
但活动计数始终为零。为什么? java 版本是 FreeBSD 上的 openJDK 8
太多的事情可能会出错,最明显的是:
maximumPoolSize
设置为 1000,这是一个幻数,与程序 运行 所在的硬件无关。Back-pressure
,您使用LinkedBlockingQueue
来欢迎任何新任务,您可能需要考虑使用ArrayBlockingQueue
并给它一个capacity
。
配置 maximumPoolSize
取决于您的应用程序,您的任务是 compute bound
?然后,池大小大于生产机器(而非开发机器)上可用内核的数量不会给你带来任何好处,而是为上下文切换和内存消耗的开销付出代价。
Java中有一个非常有用的方法可以获取你拥有的核心数,请使用它。
Runtime.getRuntime().availableProcessors();