我有一个程序可以生成线程 (~5-150) 来执行一堆任务。最初,我使用 FixedThreadPool
因为 this similar question建议它们更适合生命周期更长的任务,并且由于我对多线程的了解非常有限,我认为线程的平均生命周期(几分钟)“long living”。
但是,我最近添加了生成额外线程的功能,这样做使我超出了我设置的线程限制。在这种情况下,最好是猜测并增加我可以允许的线程数还是切换到 CachedThreadPool
这样我就不会浪费线程了?
初步尝试它们,似乎没有区别,所以我倾向于使用 CachedThreadPool
只是为了避免浪费。但是,线程的生命周期是否意味着我应该选择一个 FixedThreadPool
并只处理未使用的线程? This question看起来那些额外的线程并没有被浪费,但我会很感激你的澄清。
最佳答案
CachedThreadPool
似乎适合您的情况,因为直接将其用于长时间运行的线程不会产生负面影响。 Java 文档中关于 CachedThreadPools 适用于短任务的评论只是表明它们特别适用于这种情况,而不是它们不能用于长时间运行的任务。
CachedThreadPool
的主要问题是它会创建多达 Integer.MAX_VALUE
数量的线程,因为如果没有未使用的线程,它总是会产生一个新线程存在于缓存中。因此,如果您有长时间运行的任务,那么您更有可能增加并发线程的数量,因为这种类型的线程池不会限制并发执行的数量。如上所述,对于您的用例而言,这似乎不是问题,但需要注意。
进一步详细说明 CachedThreadPool
和 FixedThreadPool
之间的区别,Executors.newCachedThreadPool和 Executors.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/