preface
A lot of times, I want to convey the idea that you have to understand the principles before you can write code as you like. And look at the source code, it is a very important way to understand the principle.
However, before the fertilizer dynasty articles, roughly divided into three categories
-
Source code analysis, how to read the source code (refer to the Dubbo source code analysis series article)
-
How to copy a one-to-one source code (refer to the dubbo source code analysis – simple principle, and spring fusion, a than single-hand write dubbo source SPI, with git address
-
Read the source code, what problem was solved (see fat toward this operation? Analysis of why to see the source code)
The third point, I think, is particularly important. We look at the source of the purpose is to solve the problem, I think only talk about pay, do not talk about the return are playing rogue. If only to tell you to understand the principle, look at the source code, and then paste a few large sections of the source code, and then to large sections of the source code annotations. Read a large section of notes down, as if to understand, the feeling is very “substantial “.
But what we want is not this feeling of “enrichment “, but really through the source code, to solve the search can not solve the problem, only in this way. Is a harvest. If Baidu literally a search have the answer that you also look at the source code this is really loaded force
Straight into the theme
Today, in the performance group of the company’s pressure test, there is such a problem, as shown in the following figure:
At a glance, roughly the number of exceptions thrown when the Dubbo thread pool reaches its maximum number of threads. So let’s start with the basic knowledge of thread pools
Common Thread pools
-
SingleThreadExecutor: single-threaded thread pool, rarely used.
-
FixedThreadExecutor: a fixed number of thread pools
-
CachedThreadExecutor: a cache thread pool
-
ScheduledThreadExecutor: scheduled thread pool, rarely used. Well, there might be an argument here. So why does Dubbo source code use this for timed tasks? Look at the source code is the most important or to see other people’s design ideas. Dubbo was designed to rely solely on the JDK to use his scheduled tasks, and naturally chose to use the JDK’s native API to do a simple scheduled task.
Meaning of thread pool parameters and how they work
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
/ /...
}
Copy the code
Thread pools have several important parameters
CorePoolSize: The number of core threads in the thread pool
MaximumPoolSize: the maximum number of threads allowed in the thread pool
KeepAliveTime: If the current thread count > corePoolSize, the extra threads will be released after keepAliveTime
Unit: keepAliveTime Indicates the keepAliveTime unit, such as minutes or hours
WorkQueue: queue
ThreadFactory: whenever a new thread needs to be created into the thread pool, it is created through this threadFactory
Handler: That is, when the thread, queue is full, and then the strategy, such as throwing an exception, etc
So let’s assume a set of parameters to practice what this parameter means
CorePoolSize: 1 mamximumPoolSize: 3 keepAliveTime: 60s workQueue: ArrayBlockingQueue, bounded blocking queue size: 4 handler: The default strategy, threw out a ThreadPoolRejectExceptionCopy the code
1. Initially, there is a thread variable poolSize that maintains the current thread count. At this point poolSize = 0
2. Here comes a task. PoolSize(0) < corePoolSize(1)
3. Here comes a task. PoolSize(1) >= corePoolSize(1); poolSize(1) >= corePoolSize(1)
4. If the queue is also full, but poolSize < mamximumPoolSize, continue to create the thread
5. If poolSize == maximumPoolSize, then handler is executed for each task submitted, and the default is to throw an exception
PoolSize= = maximumPoolSize(3); corePoolSize=1; corePoolSize=1; corePoolSize=1; corePoolSize=1;
That’s what thread pool parameters mean and how they work
Thread pool parameter design considerations
With that in mind, let’s look at the parameter design of two common thread pools, FixedThreadExecutor and CachedThreadExecutor
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
Copy the code
public static ExecutorService newCachedThreadPool(a) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
Copy the code
So here’s the question
1. Why are FixedThreadExecutor’s corePoolSize and mamximumPoolSize designed to be the same?
2. Why was the mamximumPoolSize of CachedThreadExecutor designed to be nearly infinite?
Type on the blackboard and underline
Or the previous sentence, we look at the source code, not a large section of the source code annotations, the most important thing is after deep thinking, understand the intent of the author’s design, that is why there are so many source code analysis articles on the market, we still have to pay attention to the fat (sell a meng)
If you have a clear understanding of the thread pool principle and parameters above, you will soon understand the design idea.
For example, the thread pool determines corePoolSize first, then workQueue, and finally mamximumPoolSize. However, LinkedBlockingQueue is an unbounded queue, so it cannot determine mamximumPoolSize In terms of mamximumPoolSize, there is no big deal
For example, let’s look at the comment for SynchronousQueue:
The size of this queue is small, and if mamximumPoolSize is not designed to be large, it is easy to throw exceptions at every turn
Suggestions on thread pool usage
We’ve got the principle, we’ve got the design idea, we’ve got the code. Light theory doesn’t work, that is, how do we use thread pools in our projects? So let’s take a look at ali’s manual, and see this compelling belief and I don’t have to say anything, okay
Dubbo thread pool
So let’s take a look at the official Dubbo documentation, which I’ve always said is the best source of learning.
Regression problems
So back to the problem we had earlier. The default thread pool for Dubbo is fixed. The default thread pool for Dubbo is fixed. The default thread pool for Dubbo is fixed Trigger handle to throw an exception. That in front of the abnormal pressure measurement problem how to come, fat toward the above analysis are lying? Fat face is also a big pig hoofs??
Straight to the source
This kind of problem.search is not going to work, because it’s not going to work. So we have to go straight to the source
@SPI("fixed"Public interface ThreadPool {/** * ThreadPool ** @param url thread parameter * @returnThread pool */ @adaptive ({Constants.THREADPOOL_KEY}) Executor getExecutor(URL URL); }Copy the code
public class FixedThreadPool implements ThreadPool {
public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), newAbortPolicyWithReport(name, url)); }}Copy the code
The FixedThreadPool parameter created by Dubbo is different from that created by newFixedThreadPool. By default,Dubbo’s FixedThreadPool,maximumPoolSize = 200, is a small SynchronousQueue. So when the number of threads exceeds 200, an exception is thrown. This is consistent with the principle of our analysis above.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Once we know how the thread pool works and the root cause of the exception, we can customize the thread pool parameters according to the business characteristics to avoid the frequent occurrence of such exceptions. Or change the default thread model of Dubbo from aLL to message, etc., which needs to be combined with the actual business situation (the real cases of the company will be abstracted into simple models later to share with you).
Write in the last
Fertilizer toward is a focus on principle, source code, development skills of technical public number, number of original thematic source code analysis, real scene source code principle combat (key).Scan the following QR codePay attention to fat, let should build rocket you, no longer screw!