In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/01 Report--
This article shows you how to understand ThreadPoolExecutor thread pool technology, the content is concise and easy to understand, it will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
Java is a multithreaded language. Basically, Java projects in a production environment are inseparable from multithreading. Thread is one of the most important system resources, if this resource is not used well, it can easily lead to program inefficiency or even problems.
There is the following scenario, there is a telephone dialing system, there are a lot of tasks that need to be dialed, the first thing to do is to consider multithreading asynchronously. If I new a Thread to execute every dialed task, when there are 10, 000 tasks to execute at the same time, then 10, 000 new threads will be created, plus various operations such as thread initial destruction, and the consumption is huge. In fact, when these functions are often realized, they do not need to be completed immediately in real time, but only hope to improve the concurrent performance of execution as much as possible within a controllable range.
Therefore, the thread pool technology is applied, and the most commonly used thread pool technology in Java is ThreadPoolExecutor. Next, let's look at the implementation of ThreadPoolExecutor as a whole. There are a lot of annotations in this class, and many of them are key points, so I don't start with annotations. Let's start with use, there's a concept.
Basic use / / core thread int corePoolSize = 5; / / maximum thread int maximumPoolSize = 10; / / thread idle recovery time int keepAliveTime = 30; / / thread idle callback time unit TimeUnit unit = TimeUnit.SECONDS; / / queue size int queueSize = 20 / / queue BlockingQueue workQueue = new ArrayBlockingQueue (queueSize); ThreadPoolExecutor executor = new ThreadPoolExecutor (corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); executor.execute (()-> {/ / do something 1}); executor.execute (()-> {/ / do something 2})
Define some necessary parameters and build a ThreadPoolExecutor object. Then call the object's execute () method. Parameter description:
CorePoolSize, the minimum number of threads retained by the thread pool. If there are less than this number of threads in the thread pool, it is created when execut () is executed.
MaximumPoolSize, the maximum number of threads allowed in the thread pool.
KeepAliveTime, unit, the time to keep a thread alive when the thread is idle.
WorkQueue, the work queue, stores submitted waiting tasks with a queue size limit.
Thread management mechanism
Many people misunderstand the relationship among corePoolSize, maximumPoolSize and workQueue. Many people think that no matter what the queue chooses, corePoolSize and maximumPoolSize must be useful, and the definition must be valid, but it is not!
Take a look at the comments on the basic rules of threads.
By default, the thread pool initially has 0 threads. When a task is received, a new thread is created if the number of surviving threads in the thread pool is less than the corePoolSize core thread.
If all running core threads are busy, beyond the tasks handled by the core thread, the executor chooses to queue the task more than to create a new thread.
If a task cannot be submitted to the queue, a new thread will be created if the maximum number of threads is not exceeded. If you exceed it, you will report an error.
In addition, if you want to have a core thread when the thread is initialized, you can call prestartCoreThread (), which is the initial one, or prestartAllCoreThread (), which is the initial whole.
Let's look at the queuing strategy.
Submit directly, using SynchronousQueue. The feature is not to save, directly submit to the thread, if there is no thread, then create a new one.
Unlimited commit, using an unbounded queue similar to LinkedBlockingQueue. It is characterized by saving tasks that cannot be handled by the core thread, there is no upper limit to the queue, and the largest thread is useless.
Limited commit, using a similar ArrayBlockingQueue bounded queue. The feature is that tasks that exceed the core thread can be saved, and the queue has an upper limit. If the limit is exceeded, create a new thread (full of throwing errors). To better protect resources and prevent crashes is also the most commonly used queuing strategy.
From the above rules, we can see that the number of core threads and the maximum number of threads, as well as the queue structure affect each other, how to queue, the size of the queue, the maximum thread is not certain.
Let's take a look at the mechanism of survival.
When a thread exceeds the number of core threads, the thread pool keeps the thread alive for keepAliveTime time, and beyond that time the thread is destroyed. In addition, the default is valid for non-core threads, and if you want core threads to apply to this mechanism, you can call the allowCoreThreadTimeOut () method. In this case, there is no such thing as core threads.
To sum up, the thread pool keeps some threads alive after executing tasks many times, even if it is idle. The purpose of this is to reduce the overhead of thread destruction creation, and the next time there is a task that needs to be executed, you can use it by taking the thread directly from the pool. But the core thread cannot maintain too much because it also requires a certain amount of overhead. The maximum number of threads protects the stability of the entire system and avoids crowded threads when concurrency is large. The work queue ensures the order of tasks and temporary storage, and the reliability of the system. The purpose of the thread survival rule is similar to that of maintaining the core thread, but reduces its survival time.
There is also a reject mechanism, which provides solutions for some abnormal situations.
Ctl thread state control
This ctl variable is the core control state of the entire thread pool.
This ctl represents two variables.
WorkerCount, the number of threads in effect. It can basically be understood as a living thread, but there is a temporary difference at some point.
RunState, running status of the thread pool. The lower 29 bits of ctl (int 32 bit) represent workerCount, so the maximum number of threads is (2 ^ 29)-1. The other three bits represent runState.
RunState has the following states:
RUNNING: receive new tasks and process queue tasks.
SHUTDOWN: no new tasks are received, but queue tasks are processed.
STOP: no new tasks are received, no queued tasks are processed, and all tasks in process are interrupted.
TIDYING: all tasks are terminated and the valid thread is 0. The terminated () method is triggered.
TERMINATED: when the execution of the terminated () method ends.
When shutdown () is called, the state changes from RUNNING to SHUTDOWN, no new tasks are received, and the tasks in the queue are processed. If shutdownNow () is called, the state changes directly to STOP. When the thread or queue is empty, the state becomes TIDYING. When terminated () is finished, it becomes TERMINATED.
Execute ()
With an understanding of the above rules and mechanisms, now start from this entry to see the source code, exactly how the whole process is implemented.
If less than the core thread is running, use this task to try to create a new thread.
If a task successfully joins the team, check the downline pool status again to see if you need to join the team, because the status may have sent a change during the enrollment process. If queuing is confirmed and there is no surviving thread, create a new empty thread.
If you can't join the team, try to create a new thread, if both fail. Reject this task.
For the second point, why create a new thread at last? It is easy to guess that there will be a polling mechanism to take the next task out of the queue and directly take advantage of this idle thread.
Comments basically explain all the code, and the code is nothing special. The most important of these is the addWoker () method, let's take a look.
AddWoker ()
Let's first understand the overall idea of this method.
As can be seen from the description, addwoker failure occurs when the thread pool is in the wrong state, the thread is full, or the thread factory fails to create a thread pool. This method is relatively long and can be divided into two stages. Look at the first paragraph first.
Retry: this way of writing, if you look less at the source code, should be unprecedented. This is a circular positional marker, which is one of the syntax of java. Looking back at the code, the for loop is also nested with a for loop, and retry: marks the first for loop, followed by break and continue statements that point to retry. This indicates that both break and continue are for loops that operate on the outer layer. Retry can be any legal character for variable naming.
Then take a look at the if statement of the outgoing for loop
This if determines that the return false;, queue that you want to execute is empty is a necessary condition. Because addWork () not only receives new tasks, but also calls tasks in the processing queue. As mentioned earlier, tasks in the queue will also be processed in the SHUTDOWN state, so if the queue is not empty, it will continue to execute.
For for loops in the inner layer
It will first determine whether the data of worker meets the definition of corePoolSize and maximumPoolSize. If not, a failure will be returned. Then try CAS to make workerCount augment, and if CAS fails, continue to spin until you succeed. Unless the state of the thread pool changes, send back to the outer for loop and re-execute to determine the state of the thread pool.
The code in the first paragraph is to let workerCount add itself if it meets the conditions.
Second paragraph of code
This paragraph is easy to understand, first create a Worker object, this Worker contains a thread created by the thread factory, and a task that needs to be executed (which can be null). If the thread is created successfully, add a reentrant lock to put the newly created Worker object into the workers member variable, and you need to re-determine the state of the thread pool and the state of the new thread before joining. If worker is added to the workers member variable, start the new thread. Finally, if the addition fails, addWorkFailed (w) is executed.
If it fails, the locking operation rolls back the wokers and workerCount, and then determines the status to see if the thread pool needs to be terminated.
This is the approximate flow of addWorker ().
For other methods, there is nothing special, here is no longer too much description, interested can read the source code. Review and summarize the core points above
When the core thread is full and busy, the thread pool tends to queue submitted tasks rather than create new threads.
Depending on the queue you choose, maximumPoolSize may not be useful. There are three different strategies.
Ctl is the core control state of the thread pool, including the runState thread pool running status and the number of workCount valid threads.
Retry: is a syntax for marking loops, and retry can be any legal character for variable naming.
The above content is how to understand ThreadPoolExecutor thread pool technology, have you learned the knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.