核心池大小与ThreadPoolExecutor中的最大池大小

use*_*266 74 threadpoolexecutor

当我们谈论ThreadPoolExecutor时,核心池大小和最大池大小之间究竟有什么区别?可以借助一个例子来解释吗?

use*_*266 106

来自这篇博文:

举个例子.起始线程池大小为1,核心池大小为5,最大池大小为10,队列为100.

当请求进入时,线程将最多创建5个,然后任务将被添加到队列中,直到达到100.当队列已满时,将创建最新的线程maxPoolSize.一旦所有线程都在使用并且队列已满,任务将被拒绝.随着队列的减少,活动线程的数量也会减少.

  • 是的,这是正确的.如果队列中有任务,则只会在corePoolSize之外添加线程.队列达到零后,这些额外的线程将"消失". (4认同)
  • 你刚从这里复制了它http://www.bigsoft.co.uk/blog/index.php/2009/11/27/rules-of-a-threadpoolexecutor-pool-size (4认同)
  • 有一个有趣的方法`allowCoreThreadTimeOut(boolean)`允许核心线程在给定的空闲时间后被杀死.将此设置为true并设置`core threads` =`max threads`允许线程池在0和'max threads`之间缩放. (3认同)

小智 36

如果运行线程> corePoolSize&<maxPoolSize,则在总任务队列已满并且新的任务队列到达时创建新线程.

表单doc :(如果有多个corePoolSize但运行的是最多的maximumPoolSize线程,则只有在队列已满时才会创建新线程.)

现在,举一个简单的例子,

ThreadPoolExecutor executorPool = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(50));
Run Code Online (Sandbox Code Playgroud)

这里,5是corePoolSize - 意味着Jvm将为前5个任务的新任务创建新线程.并且其他任务将被添加到队列中,直到队列变满(50个任务).

10是maxPoolSize - JVM可以创建最多10个线程.表示如果已经有5个任务/线程正在运行并且队列已满,有50个待处理任务,并且如果还有一个新请求/任务到达队列,那么JVM将创建最多10个新线程(总线程数=前5个+新5个) ;

new ArrayBlockingQueue(50) =总队列大小 - 它可以在其中排队50个任务.

一旦所有10个线程都在运行,并且新任务到达,那么新任务将被拒绝.

SUN内部创建线程的规则:

  1. 如果线程数小于corePoolSize,则创建一个新线程以运行新任务.

  2. 如果线程数等于(或大于)corePoolSize,则将任务放入队列.

  3. 如果队列已满,并且线程数小于maxPoolSize,则创建一个新线程以运行任务.

  4. 如果队列已满,并且线程数大于或等于maxPoolSize,则拒绝该任务.

希望,这是HelpFul ..如果我错了请纠正我...


Bri*_*new 19

来自doc:

当在方法execute(java.lang.Runnable)中提交新任务并且运行的线程少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求.如果有多个corePoolSize但运行的maximumPoolSize线程少于maximumPoolSize,则只有在队列已满时才会创建新线程.

此外:

通过设置corePoolSize和maximumPoolSize,可以创建固定大小的线程池.通过将maximumPoolSize设置为基本无限制的值(如Integer.MAX_VALUE),可以允许池容纳任意数量的并发任务.最典型的情况是,核心和最大池大小仅在构造时设置,但也可以使用setCorePoolSize(int)和setMaximumPoolSize(int)动态更改.


Pre*_*raj 15

来源

ThreadPoolExecutor 池大小的规则

ThreadPoolExecutor's池大小的规则通常被误解,因为它没有按照您认为应该的方式或您希望的方式工作。

以这个例子为例。起始线程池大小为 1,核心池大小为 5,最大池大小为 10,队列为 100。

Sun 的方式:当请求进来时,最多会创建 5 个线程,然后将任务添加到队列中,直到达到 100。当队列已满时,最多会创建新线程maxPoolSize。一旦所有线程都在使用并且队列已满,任务将被拒绝。随着队列的减少,活动线程的数量也会减少。

用户预期的方式:当请求进入线程时,将创建多达 10 个线程,然后将任务添加到队列中,直到达到 100,此时它们被拒绝。线程数将重命名为最大值,直到队列为空。当队列为空时,线程将死亡,直到有corePoolSize剩余。

不同之处在于用户希望更早开始增加池大小并希望队列更小,而 Sun 方法希望保持池大小较小,并且只有在负载变得很大时才增加它。

以下是 Sun 的线程创建规则,简单来说:

  1. 如果线程数小于corePoolSize,则创建一个新线程来运行新任务。
  2. 如果线程数等于(或大于)corePoolSize,则将任务放入队列中。
  3. 如果队列已满,并且线程数小于maxPoolSize,则创建一个新线程来运行任务。
  4. 如果队列已满,并且线程数大于或等于maxPoolSize,则拒绝该任务。总而言之,新线程仅在队列填满时创建,因此如果您使用无界队列,则线程数不会超过corePoolSize.

有关更完整的解释,请从马口中获取:ThreadPoolExecutorAPI 文档。

有一个非常好的论坛帖子,它通过ThreadPoolExecutor代码示例的工作方式与您交谈:http : //forums.sun.com/thread.jspa?threadID=5401400&tstart=0

更多信息:http : //forums.sun.com/thread.jspa?threadID=5224557&tstart=450


Sau*_*ahu 12

在图中,仅考虑正在发生的任务添加

在此输入图像描述


小智 6

如果您决定ThreadPoolExecutor手动创建而不是使用Executors工厂类,则需要使用其构造函数之一创建和配置一个.这个类中最广泛的构造函数是:

public ThreadPoolExecutor(
    int corePoolSize,
    int maxPoolSize,
    long keepAlive,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    RejectedExecutionHandler handler
);
Run Code Online (Sandbox Code Playgroud)

如您所见,您可以配置:

  • 核心池大小(线程池将尝试坚持的大小).
  • 最大池大小.
  • 保持活动时间,此时空闲线程有资格被拆除.
  • 用于保存等待执行的任务的工作队列.
  • 拒绝任务提交时应用的策略.

限制排队任务的数量

限制正在执行的并发任务的数量,调整线程池的大小,在可预测性和稳定性方面为您的应用程序及其执行环境带来巨大好处:无限制的线程创建最终会耗尽运行时资源,因此您的应用程序可能会遇到,严重的性能问题甚至可能导致应用程序不稳定.

这只是问题的一部分的解决方案:您正在限制正在执行的任务数量,但不会限制可以提交和排队以便以后执行的作业数量.该应用程序将在以后遇到资源短缺,但如果提交率始终超过执行率,它最终将体验到它.

该问题的解决方案是:向执行程序提供阻塞队列以保存等待任务.在队列填满的情况下,提交的任务将被"拒绝".在RejectedExecutionHandler当任务提交被拒绝被调用,这就是为什么拒绝动词前一个项目中被引述.您可以实施自己的拒绝策略或使用框架提供的内置策略之一.

默认拒绝策略有执行程序抛出a RejectedExecutionException.但是,其他内置策略可以让您:

  • 默默地丢弃工作.
  • 丢弃最旧的作业并尝试重新提交最后一个作业.
  • 在调用者的线程上执行被拒绝的任务.