CachedThreadPool
似乎适合您的情况,因为直接使用长时间运行的线程没有负面影响。Java文档中关于 CachedThreadPools
适用于短任务只是表明它们特别适合这种情况,并不意味着不能用于长时间运行的任务。
使用 CachedThreadPool
的主要问题在于,它将创建多达Integer.MAX_VALUE
个线程,因为如果缓存中不存在未使用的线程,则始终会生成新线程。因此,如果您有长时间运行的任务,则更有可能增加并发线程的数量超过所需,因为此类型的线程池本身不会限制同时执行的数量。根据您描述的用例,这似乎不是一个问题,但这是需要注意的问题。
进一步阐述 CachedThreadPool
和 FixedThreadPool
之间的区别,Executors.newCachedThreadPool 和 Executors.newFixedThreadPool 在至少 open JDK 中都由相同的线程池实现支持,通过 ThreadPoolExecutor
的一个实例来实现,仅仅是线程最小值、最大值、线程结束时间和队列类型不同。
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
可以相对容易地做到这一点。这实际上取决于您的应用程序设计以及如何将任务提交给执行器服务。
ThreadPoolExecutor
,例如ThreadPoolExecutor(0, maximumPoolSize, 60L, TimeUnit.SECONDS, SynchronousQueue())
? - Abhijit Sarkar