提问者:小点点

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


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

创建一个线程池,该线程池根据需要创建新线程,但当它们可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,调用执行将重用以前构造的线程。如果没有现有线程可用,将创建一个新线程并添加到池中。六十秒内未使用的线程将被终止并从缓存中删除。因此,保持空闲足够长时间的池不会消耗任何资源。请注意,可以使用ThreadPoolExecator构造函数创建具有类似属性但不同细节(例如超时参数)的池。

从这个描述中我不清楚——在一个程序中拥有几个这样的池是否安全?或者我可能会遇到一个池在许多线程上停顿并冻结其他池的情况?


共1个答案

匿名用户

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

一方面,ThreadPoolExecator实例使用的线程数并不是有限的,JVM体系结构本身并没有限制线程数。

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

>

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

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

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

    如果有足够大数量的线程和/或太多的线程上下文切换,线程调度程序(在OS)可能会挣扎。

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

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

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

    所以…

    在一个程序中有几个这样的池是安全的吗?

    或者我可能会遇到一个池在许多线程上停顿并冻结其他池的情况。

    你不太可能得到一个“失速”…除非任务以某种方式相互作用。

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