Offer to come, dig friends take it! I am participating in the 2022 Spring Recruit Punch card activity. Click here for details

1. The background

The company launched a set of application monitoring system, which can detect some status of the application, such as memory, thread count, etc. After the application has been running for a period of time, it received a warning of excessive application thread count. I was confused at the time. After the application restarts, it returns to normal again, and soon there is a corresponding alarm about too many threads warning. There’s not a lot of regularity in the intervals.

Tips: Alarm will be raised if the number of threads exceeds 600

Then there is the troubleshooting process. Run the command

Jstack -l <pid> lists the thread pools in the applicationCopy the code

The thread pool of pool-xxx-thread-xxx is found by carefully checking the threads. The thread pool is a problem. The following code was found through code review:

@service@slf4j Public class AccountAuthServiceImpl implements AccountAuthService {// @override public Boolean bindUser(Long hrsAccountId, Long hmcAccountId){ ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2); Future<Boolean> hrsExt = executorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception {// Check whether hrsAccountId returns true; }}); Future<Boolean> hmcExt = executorService.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception {// Check whether hmcAccountId returns true; }}); try { return hrsExt.get(3, TimeUnit.SECONDS) & hmcExt.get(3, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } return false; }}Copy the code

Tips: Omitted some code, take a look at how this code looks familiar. This is similar to a problem I encountered earlier. If you are interested, check out this article: “What Happens when Java Thread Pools are misused – A Production Case”.

The code for the service above is the method that calls the Controller in the front end and then the Controller calls the service. At this point a lot of people probably don’t know what the problem is. Here’s what the problem is and how to avoid it.

2. Problem analysis

Problem 1: The thread pool thread has no custom name set

Creating a thread pool without a custom thread pool name, some might say that’s not a problem. And does not affect the operation (PS: this kind of words in the heart to say it is good do not say interview)! That’s fine, but think about why you should design a ThreadFactory that lets you customize the name. Thread thread- XXX thread- XXX thread- XXX thread- XXX thread And then by guessing that it might be a thread pool problem. If you set the custom name of the thread, you know that the thread pool is new.

Problem 2: Thread pool creation is placed in the Service method of the SpringBoot Web project

From the above code, the intention is to request the interfaces of the two services in parallel through thread pools to achieve efficiency. It also follows a lot of talk on the Internet about having twice as many threads as the CPU. A lot of people would say that there is nothing wrong with this method, that the thread-safe method terminates the variable and is collected by the garbage collector. The problem is that thread pools are different from other variables. Creating a thread pool here is equivalent to creating a thread in the method and starting it, as shown in the following code:

public boolean bindUser(Long hrsAccountId, Long hmcAccountId){ new Thread(new Runnable() { @Override public void run() { for (;;) { } } }).start(); }Copy the code

Each call to the interface creates a thread similar to the one shown above.

Tips: See why Java Thread pools are still running after the main thread ends.

I’m going to create a thread pool every time I call the interface, and then I’m going to create two threads, so if I call it 1,000 times that’s 2,000 threads. It is normal for an exposed interface to be called thousands of times at a release interval. So this will cause the number of threads in the application to slowly increase over time and as the interface is called more frequently. Until the alarm threshold is reached.

3. Causes of problems

  • In the case of question 1, not setting thread names for thread pools is often a matter of personal custom and the company does not have a code specification.
  • Problem 2 May result from knowing the benefits of a thread pool, but not knowing the life cycle of a thread pool and the considerations of a thread pool.

4. How to avoid potholes during development

  • For question 1, we should develop good coding practices during development, even if the company does not have these thread pool policies. You should do the same. It’s not just thread pools, it’s threads as well, and if there’s a problem how can you quickly locate that problem is very important in multithreading. If we set the thread prefix name that we are familiar with, we can think of and quickly locate the problem when we see a large number of thread name prefixes that developers are familiar with when troubleshooting problems. Rule: Thread pool or thread problems allow developers to quickly locate problems (by thread name)

  • There are two aspects to the second question:

    • Understanding the thread pool mechanism
    • Use of thread pools in SpringBoot projects

First of all, let’s talk about thread pooling mechanism, which is the pooling technology of JDK threads. This is intended to solve the problem of repeatedly creating threads in the process of multi-threading and the loss of time when the thread is destroyed after the use of threads. It will manage the threads that have been created, and then use the task next time without creating threads again. In the case that all threads in the thread pool are user threads, the thread pool will not be destroyed even after the main thread ends as long as the JVM does not exit and the user does not actively invoke the shutdown method of the thread pool. So in use, if thread pool isolation is required, each type of thread pool should be created only once after the project is started, rather than in the method shown above.

The second is to use thread pools in Spring Boot projects. There are two cases:

  1. Configure the + @async annotation using the Spring Boot thread pool
  2. Define your own thread pool in the service class

The first approach is often to delegate all tasks that need to be executed to a single thread pool without thread pool isolation (it can be done, but most of the time it is not). The second is a little more liberal.

The first way Spring Boot gives you some precautions to prevent the above problems from happening. But if you are unsure about the use of a technique the best way is to write a simple example to test your doubts and assumptions

5. To summarize

  • The name of the thread pool and thread must be set to a name that the developer is familiar with. This can be found in other projects and Java commands. Thread naming is an important step. Although Java provides default names, custom names are important when troubleshooting problems.
  • Using thread pools in Spring Boot allows you to use thread pools as provided by Spring Boot, or developers can customize them. But if you are not sure whether such use is correct, it is best to verify through small cases. Avoid the occurrence of the above cases.
  • We need to know what a technology is and we need to know why

I am ant back elephant, the article is helpful to you like to pay attention to me, the article has incorrect place please give correct comments ~ thank you