ThreadPoolExecutor 类似于 Executors.cachedThreadPool 但具有最大线程和队列

ThreadPoolExecutor similar to Executors.cachedThreadPool but with max threads and a queue

这是缓存的线程池:

new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

这是固定的 ThreadPoolExecutor:

new ThreadPoolExecutor( 0, 20, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

第一个可以创建 INTEGER.MAX_VALUE 个线程,这在我的情况下是不需要的。

第二个,不正确。您不能对 LinkedBlockingQueue 使用最少 0 个线程和最多 20 个线程。

来自文档:

http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html

Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to wait in the queue when all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.)

在第一种情况下使用SynchronousQueue,CachedThreadPool 确实没有用作队列的目的。它只会根据需要创建线程并且需要一个高上限。

A good default choice for a work queue is a SynchronousQueue that hands off tasks to threads without otherwise holding them. Here, an attempt to queue a task will fail if no threads are immediately available to run it, so a new thread will be constructed. This policy avoids lockups when handling sets of requests that might have internal dependencies. Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks. This in turn admits the possibility of unbounded thread growth when commands continue to arrive on average faster than they can be processed.

现在,我追求的是:

我想要的是一个你可以提交工作的执行器,如果 maxThreads 都忙,它使用一个队列,但它也允许线程空闲,并且在没有工作时不占用任何资源.

使用:

ThreadPoolExecutor ex = new ThreadPoolExecutor(0, threads, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
ex.setKeepAliveTime(idletime, TimeUnit.MILLISECONDS);

我不确定它有什么含义。该文档似乎只解释了无界 LinkedBlockingQueue 的使用,我不太确定这是什么意思,因为构造函数创建了一个最大容量为 Integer.MAX_VALUE 的队列。

文档还指出:

(And the value of the maximumPoolSize therefore doesn't have any effect.)

我想要的是最小线程池大小和最大线程池大小,用于排队工作并让线程在没有工作时空闲。

编辑

阅读这个问题和最后一部分让我考虑是否应该创建一个

new ThreadPoolExecutor(20, ??irrelevant??, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

如果

这将创建 20 个空闲线程

ex.setKeepAliveTime(60L, TimeUnit.MILLISECONDS);

已设置。

这是一个正确的假设吗?

What I want is a minimum thread pool size and a maximum thread pool size that queues up work and lets threads go idle when there is no work.

这正是具有无限队列的固定线程池为您提供的。简而言之,定义一个线程池

new ThreadPoolExecutor( 0, 20, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

这就是你所需要的。你得到的是一个最多有 20 个线程的线程池,以及一个可以接受 'infinite' 个任务的工作队列。

队列为空怎么办? ThreadPool 将有 20 个线程仍处于活动状态并在队列中等待。当他们在队列中等待时,线程挂起并且不做任何工作。

我要进行的一项更新是将 0L, TimeUnit.MILLISECONDS 更改为更高一点的值,例如 1L, TimeUnit.SECONDS。这是线程空闲期,你应该让线程多活一段时间再关闭它。

简而言之,线程池可以满足您的需求。如果在评论中让我知道,我可能会遗漏一些东西。

也许这有帮助:(如何让 ThreadPoolExecutor 在排队之前将线程增加到最大值?)