How do I evaluate how many threads are required for a thread pool?

See words such as surface, wesker is, a graduated from ordinary 2 colleges, never contact distributed, micro service, high concurrency to workplace transformation by sharing of techniques, grow up to be excellent RocketMQ community evangelist, senior architect, a consortium published book RocketMQ technology insider, welcome to pay attention to my * *, * * communication progress together.

Concurrent Java programming is a big high frequency interview questions in the first round of the interview, the thread pool is one of the typical representative, this paper will comb on the working mechanism of thread pool and put forward the soul’s question: do you know about the working mechanism of the thread pool so that you work in a thread pool is how to determine how much you need to create a thread?

1. Basic working principle of thread pool and interview guide


1.1 Core properties of Java thread pools

The core properties of a JAVA thread pool are as follows:

  • Int corePoolSize Specifies the number of core threads

  • Int maximumPoolSize Maximum number of threads in the thread pool

  • Long keepAliveTime Time for which a thread remains active

  • TimeUnit Unit of keepAliveTime

  • BlockingQueue< Runnable > workQueue Specifies the queue for squeezing tasks

  • ThreadFactory The ThreadFactory thread creates the factory class

  • RejectedExecutionHandler Handler Rejects a policy

1.2 Thread creation process when submitting a task to a thread pool

How does the thread pool create a thread when a user submits a task to the thread pool?

  1. First, the thread pool determines whether the currently created thread is smaller than corePoolSize (the number of core threads). If it is smaller, a new thread will be created to perform the task, regardless of whether the created thread is free, until the number of created threads equals the number of core threads.

  2. When the number of threads created in the thread pool is equal to the number of core core threads, when the user continues to submit a task to the thread pool, the user will first judge whether the task queue is full: 1) If the task queue is full, the user will put the task into the queue. 2) If the task queue is full, it judges whether the current number of threads exceeds the maximum number of threads. If not, it creates a new thread to execute the task. If the number of threads created in the thread pool is equal to the maximum number of threads, it executes the rejection policy.

Tip: So if the queue used by the thread pool is unbounded, the maximum number of threads becomes meaningless.

1.3 Thread Pool rejection policies and Application scenarios

By default, JUC provides the following rejection policies:

  • AbortPolicy refused, throw RejectedExecutionException directly, the default values.

  • CallerRunsPolicy Runs the run method of the task directly from the calling thread, that is, asynchronously to synchronously.

  • DiscardOldestPolicy Discards the first entered task in the task queue.

  • If a DiscardPolicy is rejected, it will not be executed “as if nothing is wrong”.

The policy can only be triggered if the thread pool is using a bounded task queue, if the queue is full, and the number of threads created by the thread pool has reached the maximum allowed thread pool.

By default, AbortPolicy is usually used.

CallerRunsPolicy The CallerRunsPolicy asynchronous synchronization does not have much significance in the case of rejection. The appropriate scenario is not worked out, because the processing of the rejection policy is slow when it needs to be executed, and the synchronous execution of the task only increases the load of the server, which is not conducive to recovery.

DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy DiscardOldestPolicy

DiscardPolicy, usually used to print logs asynchronously, is ignored in the expectation that old data will be saved.

1.4 How do I Select a blocking queue

Alibaba’s internal open source specification explicitly forbids the use of unbounded queues. If unbounded queues are used, tasks will be submitted to the thread pool without limit, which may cause memory overflow.

If an unbounded queue is used, the maximum number of threads parameter is invalidated because you can never create more threads than the number of core threads.

1.5 What is the practical use of a thread pool factory

ThreadFactory when using a thread pool, it is highly recommended to use your own ThreadFactory, which can name the threads in the thread pool. In this way, you can quickly identify the corresponding threads when using the jsatck command to view the thread stack.

1.6 Function of keepAliveTime parameter

KeepAliveTime: In layman’s terms, this parameter represents the maximum idle time of a thread, that is, how long it can live if it is not executing a task.

By default, this parameter only applies to threads that exceed the number of core threads (corePoolSize). AllowCoreThreadTimeOut can be set to true and the number of core threads will also be closed for idle.

2. How do I set up appropriate threads for the thread pool


Currently, according to some open source frameworks I’ve looked at, the number of threads is usually set based on the type of application: IO intensive, CPU intensive.

  • The IO intensive value is usually set to 2N +1, where N is the number of CPU cores

  • CPU intensive is usually set to N +1.

The actual situation is much more complicated and will not be set according to this formula. The above formula is usually suitable for framework classes, such as Netty and Dubbo, the underlying communication framework is usually set according to the above standard.

How do you set up appropriate threads for a thread pool in real business development?

In fact, for IO intensive applications, there is a formula: number of threads = number of CPU cores /(1- blocking factor)

The concept of blocking coefficient is introduced, which is generally between 0.8 and 0.9.

In our business development, it is basically IO intensive, because we often have to operate database, access to redis, ES and other storage components, involving disk IO, network IO.

So what scenario is CPU intensive? Pure computing, such as calculating the number of digits of PI, of course, we have little access to.

I/O intensive, you can consider setting more threads, the main purpose is to increase the CONCURRENCY of I/O, CPU intensive do not set multi-threading, because it will cause thread switching, but loss of performance.

Let’s use a real-world scenario to show how to set the number of threads.

An MQ consumer is deployed on a 4C8G machine. In RocketMQ, the consumer uses a thread pool to consume threads. How to set the number of threads?

If the number of threads is set to 9 according to the formula of 2n + 1, it is found in our practice that increasing the number of threads will significantly improve message processing capacity, indicating that 2n + 1 is not suitable for business scenarios.

If the number of threads = number of CPU cores /(1- blocking coefficient) the blocking coefficient is 0.8, the number of threads is 20. The blocking factor is 0.9, which is about 40 threads, 20 threads, I think.

If we find that the database operation takes a lot of time, we can continue to increase the blocking factor to increase the number of threads.

** How can we tell if we need to add more threads? ** In fact, you can use the jstack command to check the thread stack of the process. If you find that most of the threads in the thread pool are waiting for the task, it indicates that the thread is sufficient, as shown in the following figure:

If most threads are running, you can continue to increase the number of threads appropriately.

This issue is introduced here, I hope to help you, but also hope that a key three even, to the author some encouragement.

Share my RocketMQ Online Case Study ebook:

Middleware interest circle

RocketMQ Technology Insider author maintenance, mainly into the system analysis of JAVA mainstream middleware architecture and design principles, to build a complete Internet distributed architecture system, help break the workplace bottleneck.

How to obtain: pay attention to the “Middleware Interest circle”, reply RMQPDF can be obtained.

TOP5 best articles of the yearCopy the code

Here’s some advice from a 10-year IT veteran for new employees

“I” was flattered by Ali Baba

How can programmers increase influence

How to read source code efficiently

Another way FOR me to get involved in the RocketMQ open source community