What is a thread pool?
A thread pool means a bunch of threads? Not exactly. A thread pool can have only one thread or multiple threads. The biggest role of the pool is to manage and reuse threads. Thread pools can help us create threads, and they can also help us destroy threads. But when it comes to multiplexing threads, the thread stops automatically after Thread.start executes the Runnable.run method, which means that the Thread object can only call the start method once. In this case, how does the thread pool reuse threads?
Let’s dive deep into the source code
The principle of the thread pool
We still start with the source code of the thread pool
In the execution method of the thread pool, we found an API that appears frequently, let’s see what this code does.
We can see that the thread pool gets the task and then handle over it to the Worker class to processing
This class creates a Thread object.
A very important detail is that when a thread is created, it is not the Runnable object we gave to the thread pool that is passed in, but the Worker object itself, when the thread starts, the run method of the Worker class will be executed.
Here we can see that we just passed the Runnable object, and then started a while loop. The loop means: as long as the task object is not empty, then task = getTask () will be called until the obtained task object is empty. will stop the loop
So what’s going on in the getTask() method, let’s see
Through these two pieces of code above, we know that getTask is actually taking out the Runnable object from the blocking queue
Through these, we can conclude that the principle of thread pool reuse thread is not our Runnable object passed in when creating a Thread object, but a Runnable class customized through the thread pool. The main function of this class is not only to execute our Runnable object. When the task we pass is executed by a thread, it will also traverse other unexecuted tasks in the blocking queue, so that one thread can execute multiple Runnable objects. This is the thread pool complex. The principle of using threads.
When to use thread pools
Through the source code, we learned the working mechanism of the thread pool, so the question is, when should we use the thread pool, and when should not?
This question is actually very simple. The source code has already told us the answer. When there is only one thread in the thread pool and only one task is performed, we can consider creating a Thread object directly to perform this task without using the thread pool.
when the life cycle of the thread pool is only a single task, there is no advantage at all, but if there are multiple tasks running at same time, the thread pool can help us reduce the number of threads
Thread pool core parameters
Next, let’s talk about several core parameters for creating a thread pool
corePoolSize is the number of core threads, what is the number of core threads? The source code comments have been written clearly, that is, the minimum number of threads, which stipulates that there must be at least a few threads in the thread pool working. These core threads must survive when there are no tasks to execute, unless we set the live time of core thread. otherwise these core threads will never stop working.
maximumPoolSize is the maximum number of threads, which includes not only the number of core threads, but also the number of non-core threads, so the question is, what are non-core threads?
The biggest difference between core threads and non-core threads is that core threads will not be recycled without tasks, while non-core threads will be recycled once there are no tasks.
workQueue is a blocking queue, why use a queue (Queue), because the queue is first-in-first-out, the first-in task is taken out first, and the final first-in task is most likely to be executed first, this queue will also used to store some unexecuted tasks. Let us have an experiment.
Experimental scenario: number of core threads = 1, maximum number of threads = 3, open for loop to execute 10 tasks, task content: sleep for 1 second and print the current thread name
- When the capacity of the blocking queue is infinite, only 1 thread of 10 tasks is queued for execution
2. When the blocking queue capacity is set to 10 or 9, only 1 thread will be queued for 10 tasks.
3. When the blocking queue capacity is set to 8, 2 threads of 10 tasks appear concurrently executing
4. When the blocking queue capacity is set to 7, 3 threads of 10 tasks appear concurrently executing
5. When the blocking queue capacity is set to 6, the thread pool throws an exception, indicating that it refuses to execute the task
When adding a new task to the thread pool, if the core thread is idle, the task will be directly handed over to the core thread for processing, otherwise the task will be stored in the blocking queue, when the number of tasks in the blocking queue exceeds the maximum , non-core threads will be started for execution. If the total number of current tasks > the maximum capacity of the blocking queue + the maximum number of threads, the thread pool will refuse to execute the task.
keepAliveTime is the survival time of the non-core thread. When the non-core thread in the thread pool has no tasks to execute, if no task is executed after the specified time, then the non-core thread will be recycled after the timeout. If We do not specify this time, then these non-core threads will never be recycled.
Four thread pools provided by the system
- Here, a thread pool with the number of core threads and the maximum number of threads is created is 1. It is simple to understand that this thread pool has only one thread, just like its method name (new Single Thread Executor)
2. This thread pool is very similar to the previous thread pool. The number of core threads and the maximum number of threads both use the same value, except that the previous thread pool is fixed to 1, and this thread pool can customize this value.
3. This thread pool does not have the number of core threads, nor does it limit the maximum number of threads, so it can be concluded that the threads in this thread pool are all non-core threads, and it is also stipulated that the survival time of non-core threads cannot exceed 60 seconds.
4. The last feature of the thread pool is that the number of core threads is fixed, but the maximum number of threads is not limited, and the idle time of non-core threads cannot exceed 10 milliseconds.