在 Java 程序中使用多个 Executors.newCachedThreadPool() 是否安全?

Is it safe to have multiple Executors.newCachedThreadPool() in a Java program?

此方法的规范:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool()

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors.

我从这个描述中不清楚 - 在一个程序中拥有多个这样的池是否安全?还是我可能会 运行 遇到这样一种情况,即一个池在多个线程上停顿并冻结其他池?

我认为对此没有明确的是/否答案。

一方面,ThreadPoolExecutor 实例消耗的线程数量不是有限的。 JVM架构本身不限制线程数。

另一方面,OS / 环境可能会有一些限制:

  • OS可能对其支持的本机线程总数有硬性限制。

  • OS可能限制给定进程(在本例中为 JVM)可以创建的本机线程数。这可以使用 ulimitcgroup 限制以及可能的其他方式来完成。

  • 一个Java线程堆栈在典型的64位JVM上的大小为1MB(默认)。如果您尝试 start() 太多线程,您可能 可能 运行 内存不足并获得 OOME。

  • 如果有足够多的线程and/or太多的线程上下文切换,线程调度器(在OS)可能奋斗.

    (上下文切换通常发生在线程执行阻塞系统调用或必须等待锁或通知时。每次切换上下文时都会有硬件相关的开销:保存和恢复寄存器、切换虚拟内存上下文、刷新内存缓存等)

另一方面,除了线程池的数量和大小之外,还有其他因素可能会导致问题。例如,如果线程任务相互交互,您可能会遇到以下原因的问题:

  • 锁定共享对象时发生死锁,
  • 过多的共享锁争用导致资源匮乏,
  • 太多工作导致超时,或者
  • 优先级反转问题...如果您尝试使用优先级来“管理”工作负载。

所以...

Is it safe to have several of these pools in a single program?

Or would I potentially run into a situation where one pool stalls on many threads and freezes up other pools.

除非任务以某种方式相互作用,否则您不太可能会遇到“停顿”。

但是如果您有太多 运行 可用线程竞争 CPU,每个线程将(平均)获得有限数量的可用内核中的一小部分。锁争用或过多的上下文切换会进一步降低速度。