With the increasing number of CPU cores, it is inevitable to use multi-threading technology to make full use of its computing power. Therefore, multi-threading technology is a technology that server developers must master.
The creation and destruction of threads involve system calls and consumes system resources, so thread pooling technology is introduced to avoid frequent thread creation and destruction.
In Java, there is an Executors tool class that can create a thread pool for us. The essence is to new a ThreadPoolExecutor object. Thread pools are almost also a must-take in interview questions. This section combines the source code to talk about the working principle of ThreadExecutor
1. Thread pool creation
Let’s first look at the most complete constructor parameters of ThreadPoolExecutor:
① corePoolSize: The number of core threads in the thread pool. To put it bluntly, even if there are no tasks in the thread pool, there will be corePoolSize threads waiting for tasks.
②maximumPoolSize: The maximum number of threads. No matter how many tasks you submit, the maximum number of worker threads in the thread pool is maximumPoolSize.
③ keepAliveTime: The survival time of the thread. When the number of threads in the thread pool is greater than corePoolSize, if there is no task to be executed after waiting for keepAliveTime, the thread exits.
⑤unit: This is used to specify the unit of keepAliveTime, such as seconds: TimeUnit.SECONDS.
⑥ workQueue: A blocking queue, and the submitted tasks will be placed in this queue.
⑦ threadFactory: a thread factory, used to create threads, mainly to name the thread. The default factory thread name is pool-1-thread-3.
⑧Handler: Reject policy, called when the threads in the thread pool are exhausted and the queue is full.
The above are the parameters used when creating a thread pool. Interviewers often ask this question during interviews.
2. Thread pool execution process
Here is a diagram to illustrate the execution process of the thread pool
When a task is submitted to the thread pool, it will first determine whether the current number of threads is less than corePoolSize. If it is less than, a thread will be created to execute the submitted task. Otherwise, the task will be put into the workQueue queue. If the workQueue is full, it will determine whether the current number of threads is less than maximumPoolSize. If it is less than, a thread will be created to execute the task. Otherwise, a handler will be called to indicate that the thread pool refuses to receive the task.
Here, take the source code of jdk1.8.0_111 as an example to see the specific implementation.
1. First look at the executor method of thread pool
①: Determine whether the current number of active threads is less than corePoolSize. If it is less than, call addWorker to create a thread to execute tasks
②: If it is not less than corePoolSize, add the task to the workQueue queue.
③: If the workQueue is put into the workQueue, the creation thread will execute the task. If the creation thread fails at this time (the current number of threads is not less than maximumPoolSize), reject will be called (internal call handler) and refuse to accept the task.
2. Let’s look at the addWorker method implementation
This piece of code is when creating a non-core thread, that is, core equals false. Determine whether the current number of threads is greater than or equal to maximumPoolSize. If it is greater than or equal to false, that is, the creation of thread failed in ③ mentioned above.
The second half of the addWorker method:
① Create a Worker object and instantiate a Thread object.
②Start this thread
3. Go to Worker to see its implementation
You can see that threadFactory is called when creating a Worker to create a thread. Starting a thread in the above ② will trigger the Worker's run method to be called by the thread.
4. Next, let’s take a look at the logic of the runWorker method.
The thread calls runWoker, and will call the getTask method while loop to read the task from the workerQueue, and then execute the task. As long as the getTask method does not return null, this thread will not exit.
5. Finally, let’s take a look at the getTask method implementation
① Let's ignore allowCoreThreadTimeOut, the default value of this variable is false. wc>corePoolSize determines whether the current number of threads is greater than corePoolSize.
② If the current number of threads is greater than corePoolSize, the poll method of workQueue will be called to obtain the task, and the timeout is keepAliveTime. If the time of keepAliveTime exceeds the time limit, the poll returns null, and the while mentioned above will exit in sequence, and the thread will be executed.
If the current number of threads is less than corePoolSize, the take method of workQueue will be called to block at the moment.
The above article is based on the working principle and source code interpretation of thread pool. This article is all the content shared by the editor. I hope it can give you a reference and I hope you can support Wulin.com more.