The thread pool is actually a pooling technology implementation. The core idea of pooling technology is to achieve resource reuse and avoid the performance overhead caused by repeated creation and destruction of resources. The thread pool can manage a bunch of threads, so that the threads will not be destroyed after completing the task, but continue to process the tasks submitted by other threads.
Benefits of using thread pools
Reduce resource consumption. Reduce the consumption caused by thread creation and destruction by reusing the created threads.
Improve response speed. When a task arrives, it can be executed immediately without waiting for the thread to be created.
Improve thread manageability. Threads are scarce resources. If they are created without limit, they will not only consume system resources but also reduce system stability. Using thread pools can achieve unified allocation, tuning, and monitoring.
Construction parameters
corePoolSize: The thread pool used for workNumber of core threads。
maximumPoolSize:Maximum number of threads, the maximum number of threads allowed to be created by the thread pool. When the number of threads in the thread pool reaches corePoolSize, if the task queue is full and new tasks need to be processed, the thread pool will create new threads (but the total number does not exceed maximumPoolSize) to process these tasks.This is equivalent to the queue area being full, and later threads can directly jump in line.) If the number of tasks exceeds maximumPoolSize and the task queue is full, the thread pool will handle these unexecutable tasks according to the rejection strategy.
keepAliveTime: The survival time of threads created after exceeding corePoolSize or all threadsMaximum survival time, depending on the configuration.
unit:keepAliveTime 的time unit。
workQueue:Task Queue, is a blocking queue. When the number of threads reaches the number of core threads, the tasks will be stored in the blocking queue. Common implementation: Implementation class of the BlockingQueue interface, such as ArrayBlockingQueue, LinkedBlockingQueue, etc.
threadFactory: used by thread pool to create threadsfactory。
handler:Rejection Strategy; When the queue is full and the number of threads reaches the maximum number of threads, this method will be called to process the task.
How to set parameters
1. Determine the number of core threads (corePoolSize)
CPU-intensive tasks: For CPU-intensive tasks, the number of core threads is usually set between 1 and 2 times the number of CPU cores. This ensures full utilization of CPU resources while avoiding excessive context switching.
IO-intensive tasks: For IO-intensive tasks, since threads will not occupy the CPU when waiting for IO operations, you can set a higher number of core threads. Generally speaking, the number of core threads can be set to more than twice the number of CPU cores so that more tasks can be processed while waiting for IO.
Mixed tasks: If the application contains both CPU-intensive and IO-intensive tasks, you need to balance the setting of the number of core threads based on the specific situation.
2. Determine the maximum number of threads (maximumPoolSize)
Resource-constrained environments: In resource-constrained environments (such as embedded systems or cloud servers), it is necessary to limit the maximum number of threads to prevent too many threads from occupying resources.
High-concurrency systems: For systems that need to handle a large number of concurrent requests, the maximum number of threads can be appropriately increased to improve the system's concurrent processing capabilities. However, the setting of the maximum number of threads should be based on comprehensive considerations of the system's load capacity and resource conditions.
3. Set thread idle time (keepAliveTime)
CPU-intensive applications: For CPU-intensive applications, you can usually set the thread idle time to a shorter value, because CPU resources are very valuable and you don't want too many idle threads to occupy resources. In some cases, you can even set it to 0, indicating that non-core threads are not reserved.
IO-intensive applications: For IO-intensive applications, since threads do not occupy CPU resources when waiting for IO operations, you can set the thread idle time to a longer value (such as more than 1 minute) to avoid performance overhead caused by frequent thread startup and destruction.
4. Select the workQueue
Bounded Queues:Using bounded queues can limit the waiting time of tasks in the queue and avoid memory overflow due to too many tasks. However, if the queue length is set too small, tasks may be rejected. (Generally choose bounded queue)
Unbounded queue: Using an unbounded queue allows you to cache all tasks as much as possible, but you need to pay attention to memory consumption. If an unbounded queue is used, the maximum number of threads in the thread pool may become invalid because the thread pool will not try to create new threads to process tasks in the queue.
5. Configure thread factory (threadFactory)
The thread factory is used to create new threads. By customizing the thread factory, you can set the thread priority, daemon thread status and other properties, and you can also give the thread a meaningful name to facilitate problem diagnosis in the JVM.
6. Configure rejection strategy (handler)
When the thread pool cannot process new tasks (that is, the number of threads has reached maximumPoolSize and the task queue is full), you need to configure a rejection strategy to handle these unexecutable tasks. Common rejection strategies includeThrow an exception directly、Use the caller's thread to execute the task、Ignore new tasks and discard the oldest tasks in the queueEtc. You can also customize the rejection strategy as needed.