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

太多的事情可能会出错,最明显的是:

  1. maximumPoolSize 设置为 1000,这是一个幻数,与程序 运行 所在的硬件无关。

  2. Back-pressure,您使用 LinkedBlockingQueue 来欢迎任何新任务,您可能需要考虑使用 ArrayBlockingQueue 并给它一个 capacity

配置 maximumPoolSize 取决于您的应用程序,您的任务是 compute bound?然后,池大小大于生产机器(而非开发机器)上可用内核的数量不会给你带来任何好处,而是为上下文切换和内存消耗的开销付出代价。

Java中有一个非常有用的方法可以获取你拥有的核心数,请使用它。

Runtime.getRuntime().availableProcessors();