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

但是,我最近添加了产生更多线程的功能,这样做使我超出了我设置的线程限制。在这种情况下,最好猜测并增加我可以允许的线程数,或者切换到CachedThreadPool以免浪费线程?

初步尝试将它们都尝试一下,似乎没有什么区别,所以我倾向于使用CachedThreadPool以避免浪费。但是,线程的生命周期是否意味着我应该改为选择FixedThreadPool并仅处理未使用的线程? This question使得这些多余的线程似乎没有浪费,但我希望您能澄清一下。

最佳答案

CachedThreadPool正是您应使用的情况,因为长时间运行线程不会使用CachedThreadPool。 java doc中关于CachedThreadPools适用于短期任务的评论仅表明它们特别适用于此类情况,而不是它们不能或不应用于涉及长期运行任务的任务。

为了进一步详细说明,Executors.newCachedThreadPoolExecutors.newFixedThreadPool都由相同的线程池实现(至少在开放式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不会为您限制它们,因此您可能需要编写自己的代码以确保您不会运行太多线程。这实际上取决于您的应用程序的设计以及如何将任务提交给执行者服务。

07-24 18:45