java - FixedThreadPool 与 CachedThreadPool : the lesser of two evils

标签 java multithreading threadpool executorservice java.util.concurrent

我有一个程序可以生成线程 (~5-150) 来执行一堆任务。最初,我使用 FixedThreadPool 因为 this similar question建议它们更适合生命周期更长的任务,并且由于我对多线程的了解非常有限,我认为线程的平均生命周期(几分钟)“long living”。

但是,我最近添加了生成额外线程的功能,这样做使我超出了我设置的线程限制。在这种情况下,最好是猜测并增加我可以允许的线程数还是切换到 CachedThreadPool 这样我就不会浪费线程了?

初步尝试它们,似乎没有区别,所以我倾向于使用 CachedThreadPool 只是为了避免浪费。但是,线程的生命周期是否意味着我应该选择一个 FixedThreadPool 并只处理未使用的线程? This question看起来那些额外的线程并没有被浪费,但我会很感激你的澄清。

最佳答案

CachedThreadPool 似乎适合您的情况,因为直接将其用于长时间运行的线程不会产生负面影响。 Java 文档中关于 CachedThreadPools 适用于短任务的评论只是表明它们特别适用于这种情况,而不是它们不能用于长时间运行的任务。

CachedThreadPool 的主要问题是它会创建多达 Integer.MAX_VALUE 数量的线程,因为如果没有未使用的线程,它总是会产生一个新线程存在于缓存中。因此,如果您有长时间运行的任务,那么您更有可能增加并发线程的数量,因为这种类型的线程池不会限制并发执行的数量。如上所述,对于您的用例而言,这似乎不是问题,但需要注意。

进一步详细说明 CachedThreadPoolFixedThreadPool 之间的区别,Executors.newCachedThreadPoolExecutors.newFixedThreadPool两者都通过 ThreadPoolExecutor 的实例由相同的线程池实现(至少在开放的 JDK 中)支持,只是参数不同。区别只是它们的线程最小值、最大值、线程终止时间和队列类型。

public static ExecutorService newFixedThreadPool(int nThreads) {
     return new ThreadPoolExecutor(nThreads, nThreads,
                                   0L, TimeUnit.MILLISECONDS,
                                   new LinkedBlockingQueue<Runnable>());
 }

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                 60L, TimeUnit.SECONDS,
                                 new SynchronousQueue<Runnable>());
}

FixedThreadPool 确实有它的优势,当您实际上想要使用固定数量的线程时,您可以在知道线程数量的同时向执行器服务提交任意数量的任务线程将保持在您指定的级别。如果您明确想要增加线程数,那么这不是合适的选择。

然而,这确实意味着 CachedThreadPool 可能遇到的一个问题是关于限制并发运行的线程数。 CachedThreadPool 不会为您限制它们,因此您可能需要编写自己的代码以确保不会运行太多线程,您可以通过实例化自己的 ThreadPoolExecutor 相对轻松地做到这一点 具有您想要的行为特征。这实际上取决于您的应用程序的设计以及如何将任务提交给执行器服务。

关于java - FixedThreadPool 与 CachedThreadPool : the lesser of two evils,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17957382/

相关文章:

java - 制作静态可重入锁

java - 当其他任务完成时,强制 BufferedWriter 从 BlockingQueue 写入

java - HTTP 状态 500 - servlet 异常的 Servlet.init()

用于删除日期模式字符串中年份的 Java 正则表达式

java - 无法将 json 转换为 java pojo 类?

java - 在所有线程完成之前从 java 方法返回

java - 从正在运行的线程读取数据

java - 如何将Servlet项目部署到一些在线服务器托管

java - Sun JVM 如何将 Java 线程映射到 Windows 线程?

python - 如何在 python 中的线程之间传递异常