不可能做一个缓存线程池大小限制? [英] Impossible to make a cached thread pool with a size limit?

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

问题描述



下面是静态Executors.newCachedThreadPool是如何使用的:在标准Java库中实现:

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



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

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

现在如果你使用这个并提交3个任务,一切都会很好。



尝试此操作:

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

将导致所有线程顺序执行。也就是说,线程池永远不会产生多个线程来处理你的任务。



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



编辑:我想要的东西完全像缓存的线程池(它创建线程按需,然后杀死他们超时后)限制它可以创建的线程数,以及一旦线程达到线程限制,就可以继续对其他任务进行排队。根据sjlee的回应这是不可能的。看看ThreadPoolExecutor的execute()方法确实是不可能的。我需要子类ThreadPoolExecutor和覆盖execute()有点像SwingWorker的,但什么SwingWorker在其execute()是一个完整的黑客。

解决方案<



当任务提交时,


  1. 如果线程池未达到内核大小,则会创建新线程。

  2. 如果已达到内核大小

  3. 如果已经达到核心大小,没有空闲线程,并且队列已满,它会创建新线程(直到它达到

  4. 如果已达到最大大小,则没有空闲的线程,并且队列已满,拒绝策略将启动。

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



在第二个例子中,选择的队列是一个LinkedBlockingQueue,它具有无限大小。因此,你会遇到行为#2。



你不能真正地修改缓存类型或固定类型,因为他们的行为几乎完全确定。



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

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


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

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>());

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

Trying this:

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.

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

Edit: 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.

解决方案

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

When tasks are submitted,

  1. If the thread pool has not reached the core size, it creates new threads.
  2. If the core size has been reached and there is no idle threads, it queues tasks.
  3. If the core size has been reached, there is no idle threads, and the queue becomes full, it creates new threads (until it reaches the max size).
  4. If the max size has been reached, there is no idle threads, and the queue becomes full, the rejection policy kicks in.

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).

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

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆