Java Spring ThreadPoolTask​​Executor中corePoolSize和maxPoolSize有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1878806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:28:06  来源:igfitidea点击:

What is the difference between corePoolSize and maxPoolSize in the Spring ThreadPoolTaskExecutor

javaspringmultithreading

提问by rabbit

I have to send out massEmails to all users of a website. I want to use a thread pool for each email that is sent out. Currently I have set the values to :

我必须向网站的所有用户发送大量电子邮件。我想为发送的每封电子邮件使用一个线程池。目前我已将值设置为:

<property name="corePoolSize" value="500" />
<property name="maxPoolSize" value="1000" />

What is the difference between the two and will it scale. Currently I have approx. 10000 users.

两者有什么区别,是否会扩展。目前我有大约。10000 个用户。

回答by Thilo

corePoolSizeis the minimum number of threads used by the pool. The number can increase up to maxPoolSize. When the load goes down, the pool will shrink back to corePoolSize.

corePoolSize是池使用的最小线程数。数量最多可以增加到maxPoolSize。当负载下降时,池将收缩回corePoolSize

Sending email seems to be an I/O bound operation. I do not think having 500 threads will make it faster.

发送电子邮件似乎是一个 I/O 绑定操作。我认为拥有 500 个线程不会使它更快。

回答by skaffman

The javadoc says it best:

javadoc 说得最好

When a new task is submitted [...], and fewer than corePoolSizethreads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSizebut less than maximumPoolSizethreads running, a new thread will be created only if the queue is full. By setting corePoolSizeand maximumPoolSizethe same, you create a fixed-size thread pool. By setting maximumPoolSizeto an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks.

当提交一个新任务 [...] 并且corePoolSize运行的线程数少于一个时,即使其他工作线程空闲,也会创建一个新线程来处理请求。如果运行的线程多于corePoolSize但少于 maximumPoolSize线程,则只有在队列已满时才会创建新线程。通过设置 corePoolSizemaximumPoolSize相同,你创建了一个固定大小的线程池。通过设置 maximumPoolSize为一个基本上无限的值,例如 Integer.MAX_VALUE,您可以允许池容纳任意数量的并发任务。

As for your specific situation, sending 500 emails all at the same time is pointless, you'll just overwhelm the mail server. If you need to send a large number of emails, then use a single thread, and send them down the pipe one at a time. The mail server will handle this much more gracefully than 500 separate connections.

至于您的具体情况,同时发送 500 封电子邮件是没有意义的,您只会使邮件服务器不堪重负。如果您需要发送大量电子邮件,请使用单个线程,并一次发送一个。邮件服务器将比 500 个单独的连接更优雅地处理这个问题。

回答by Osify

You should consider to increase value of queueCapacitythan consider to increase value of corePoolSizeor maxPoolSize. Those two properties (*PoolSize) are number of pool to execute but each message would be considering in queueCapacity

您应该考虑增加queueCapacity 的值而不是考虑增加corePoolSizemaxPoolSize 的值。这两个属性 (*PoolSize) 是要执行的池数,但每条消息都将在queueCapacity 中考虑

<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="1000" />
<property name="waitForTasksToCompleteOnShutdown" value="true"/>

If you have 10000 users to send so 1000 * 10 (maxPoolSize) = 10000 but if 1000 for each thread is heavy, we can consider to increase poolSize.

如果你有 10000 个用户发送所以 1000 * 10 (maxPoolSize) = 10000 但如果每个线程 1000 很重,我们可以考虑增加 poolSize。

回答by taynguyen

Here are Sun's rules for thread creation in simple terms:

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

  1. If the number of threads is less than the corePoolSize, create a new Thread to run a new task.
  2. If the number of threads is equal (or greater than) the corePoolSize, put the task into the queue.
  3. If the queue is full, and the number of threads is less than the maxPoolSize, create a new thread to run tasks in.
  4. If the queue is full, and the number of threads is greater than or equal to maxPoolSize, reject the task.
  1. 如果线程数小于corePoolSize,则创建一个新线程来运行新任务。
  2. 如果线程数等于(或大于)corePoolSize,则将任务放入队列中。
  3. 如果队列已满,并且线程数小于maxPoolSize,则创建一个新线程来运行任务。
  4. 如果队列已满,并且线程数大于或等于maxPoolSize,则拒绝该任务。

Full article

全文

Origin answer

原答案

回答by SinhaOjas

What everyone has explained so clearly is correct. Few things to notice here is that you should always have a limited size for core-pool as well as queue. If the core-pool-size if very high, there can a high chance that many of your threads from pool are remaining unused for certain period of time since for every request new thread gets created until it reaches max-pool-size

大家解释的这么清楚是对的。这里需要注意的几件事是,您应该始终为核心池和队列设置有限的大小。如果 core-pool-size 非常高,则池中的许多线程很可能在一段时间内未使用,因为每次请求都会创建新线程,直到达到 max-pool-size

But if your machine is going to face large number of request concurrently then you should also consider that the machine size is sufficient enough : example:

但是如果您的机器将同时面临大量请求,那么您还应该考虑机器大小是否足够:例如:

If your machine size in 1 GB and queue capacity is at Integer.MAX_VALUE then there is a high chance that your machine will start rejecting the requesting at some point of time because of OutOfMemory which you can monitor in any JVM GUI tool.

如果您的机器大小为 1 GB,队列容量为 Integer.MAX_VALUE,那么您的机器很可能会在某个时间点开始拒绝请求,因为您可以在任何 JVM GUI 工具中监控 OutOfMemory。

回答by Mahesha999

In addition to what @skaffman pointed out from official docs, following also makes it more clear how these sizes are utilized:

除了@skaffman 从官方文档中指出的内容之外,以下内容也更清楚地说明了如何使用这些尺寸:

Any BlockingQueuemay be used to transfer and hold submitted tasks. The use of this queue interacts with pool sizing:

AnyBlockingQueue可用于传输和保留提交的任务。此队列的使用与池大小交互:

  • If fewer than corePoolSizethreads are running, the Executoralways prefers adding a new thread rather than queuing.
  • If corePoolSizeor more threads are running, the Executoralways prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
  • 如果少于corePoolSize线程正在运行,则Executor总是更喜欢添加新线程而不是排队。
  • 如果一个corePoolSize或多个线程正在运行,则Executor总是更喜欢将请求排队而不是添加新线程。
  • 如果请求无法排队,则会创建一个新线程,除非超过maximumPoolSize,在这种情况下,任务将被拒绝。