本文介绍了不可能制作具有大小限制的缓存线程池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎不可能制作一个缓存线程池,限制它可以创建的线程数.

It seems to be impossible to make a cached thread pool with a limit to the number of threads that it can create.

以下是标准 Java 库中静态 Executors.newCachedThreadPool 的实现方式:

Here is how static Executors.newCachedThreadPool is implemented in the standard Java library:

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

因此,使用该模板继续创建固定大小的缓存线程池:

So, using that template to go on to create a fixed sized cached thread pool:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());

现在如果你使用这个并提交3个任务,一切都会好起来的.提交任何进一步的任务将导致被拒绝的执行异常.

Now if you use this and submit 3 tasks, everything will be fine. Submitting any further tasks will result in rejected execution exceptions.

试试这个:

new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());

将导致所有线程顺序执行.即,线程池永远不会产生多个线程来处理您的任务.

Will result in all threads executing sequentially. I.e., the thread pool will never make more than one thread to handle your tasks.

这是ThreadPoolExecutor的execute方法的一个bug?或者这可能是故意的?还是有其他方法?

This is a bug in the execute method of ThreadPoolExecutor? Or maybe this is intentional? Or there is some other way?

我想要一些与缓存线程池完全相同的东西(它按需创建线程,然后在超时后杀死它们),但它可以创建的线程数量和继续排队其他任务的能力有限制一旦达到线程限制.根据 sjlee 的回应,这是不可能的.看ThreadPoolExecutor的execute()方法确实是不可能的.我需要子类化 ThreadPoolExecutor 并覆盖 execute() 有点像 SwingWorker 所做的,但 SwingWorker 在其 execute() 中所做的是一个完整的黑客.

I want something exactly like the cached thread pool (it creates threads on demand and then kills them after some timeout) but with a limit on the number of threads that it can create and the ability to continue to queue additional tasks once it has hit its thread limit. According to sjlee's response this is impossible. Looking at the execute() method of ThreadPoolExecutor it is indeed impossible. I would need to subclass ThreadPoolExecutor and override execute() somewhat like SwingWorker does, but what SwingWorker does in its execute() is a complete hack.

推荐答案

ThreadPoolExecutor有以下几个关键行为,你的问题可以用这些行为来解释.

The ThreadPoolExecutor has the following several key behaviors, and your problems can be explained by these behaviors.

提交任务时,

  1. 如果线程池未达到核心大小,则会创建新线程.
  2. 如果已达到核心大小且没有空闲线程,则将任务排队.
  3. 如果已达到核心大小,则没有空闲线程,并且队列已满,则会创建新线程(直到达到最大大小).
  4. 如果已达到最大大小,没有空闲线程,并且队列已满,则拒绝策略启动.

在第一个示例中,请注意 SynchronousQueue 的大小基本上为 0.因此,当您达到最大大小 (3) 时,拒绝策略就会启动 (#4).

In the first example, note that the SynchronousQueue has essentially size of 0. Therefore, the moment you reach the max size (3), the rejection policy kicks in (#4).

在第二个示例中,选择的队列是 LinkedBlockingQueue,其大小不受限制.因此,您会陷入行为 #2.

In the second example, the queue of choice is a LinkedBlockingQueue which has an unlimited size. Therefore, you get stuck with behavior #2.

您不能对缓存类型或固定类型进行过多修改,因为它们的行为几乎完全确定.

You cannot really tinker much with the cached type or the fixed type, as their behavior is almost completely determined.

如果你想要一个有界且动态的线程池,你需要使用正的核心大小和最大大小以及有限大小的队列.例如,

If you want to have a bounded and dynamic thread pool, you need to use a positive core size and max size combined with a queue of a finite size. For example,

new ThreadPoolExecutor(10, // core size
    50, // max size
    10*60, // idle timeout
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<Runnable>(20)); // queue with a size

附录:这是一个相当古老的答案,似乎 JDK 在内核大小为 0 时改变了它的行为.从 JDK 1.6 开始,如果内核大小为 0 并且池确实如此没有任何线程,ThreadPoolExecutor 将添加一个线程来执行该任务.因此,核心大小为 0 是上述规则的一个例外.感谢 史蒂夫 引起我的注意.

Addendum: this is a fairly old answer, and it appears that JDK changed its behavior when it comes to core size of 0. Since JDK 1.6, if the core size is 0 and the pool does not have any threads, the ThreadPoolExecutor will add a thread to execute that task. Therefore, the core size of 0 is an exception to the rule above. Thanks Steve for bringing that to my attention.

这篇关于不可能制作具有大小限制的缓存线程池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-30 04:56