“This is the 12th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

What happens when thread pools are used incorrectly? As shown below (you can analyze by yourself first) :

This is a problem found in my company’s actual work. However, this interface is not called frequently enough so there are no problems found online (release republish project will release server resources)

The goal of thread pooling is to reduce the resource consumption of thread creation and destruction, and to prevent users from consuming system resources by creating threads without limit. So Java defines thread pools for developers to use. But what happens if thread pools are not used properly? This code is written right here with a 40-meter knife held to his neck. Having joked, let’s write a similar one to see what happens and analyze why this happens and how to avoid it.

1. Example demonstration

Demo code address: github.com/mxsm/spring…

Define a Controller

@RestController
public class ThreadPoolController {

    @Autowired
    private ThreadPoolService threadPoolService;

    @GetMapping(value = "/createThreadPool")
    public boolean createThreadPool(a){
        returnthreadPoolService.createThread(); }}Copy the code

Define a ThreadPool Service to simulate the problem shown above

@Service
public class ThreadPoolService {

    public boolean createThread(a){

		// Add ThreadFactory for easy differentiation
        ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {

            /**
             * Constructs a new {@code Thread}.  Implementations may also initialize priority, name, daemon
             * status, {@code ThreadGroup}, etc.
             *
             * @param r a runnable to be executed by new thread instance
             * @return constructed thread, or {@code null} if the request to create a thread is rejected
             */
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "mxsm"); }}); executorService.submit(new Runnable() {
            @Override
            public void run(a) {
                System.out.println("King Nima."); }});return true; }}Copy the code

Then simulate the problem of a real instance of the above work by calling the interface /createThreadPool. Let’s see what happens. Package the project as a JAR package and run it locally.

Then run the project:

Request the above interface continuously after running:

See that the print instructions with execution have been requested. We then look at the thread pool with the commands: JPS and jstack -l

Note the thread status as shown below:

It’s all about waiting. What does that tell you? Thread did not die with the method completes This is very terrible, if your interface is called, the thread will continuously increase, the number of created when added to your server resources are all used up will cause the service downtime report (Java. Lang. OutOfMemoryError). How and why is this code written

Tips: there may be a lot of people did not find Executors. NewSingleThreadScheduledExecutor this is created by a single thread thread pool. So the resulting thread growth rate is 1 per call to the interface. What if it’s a pool of 100 threads? That could quickly lead to service outages. Suffice it to say that the single-threaded thread pool interface is not called very often

2. Cause analysis and solution

2.1 Possible cause analysis

  1. I am not familiar with several patterns of Spring beans. By default, beans are singletons and I am not familiar with the life cycle of beans. In the previous case, the Bean will accompany the Spring container throughout its lifecycle from startup to death. Context: I don’t stop serving UserActionImpl the entire object instance will always exist in singleton mode.

  2. Do not understand thread pooling, except that Spring Bean methods are thread-isolated. All the variables inside the method are reclaimed. This is where thread pools differ from other variables. The specific principle can go to study the thread pool source code. So how do we test this?

As you can see from the picture above, the word “done” is printed out and the service should have stopped but it didn’t. This is because of thread pools.

  1. Or you might just want to execute the code in Runnable asynchronously, but you might want to use the wrong code when you hear about the benefits of Thread pools.

  2. It is also possible that the code was written carelessly to define the thread pool as an attribute variable of the class. But I was careless and put it in the wrong place

2.2 Solutions

  1. Execute Runnable instances without using Thread pools directly with new Threads
  2. Define the thread pool as a property variable of the class

3. Proper use of thread pools

  • It is best to keep each thread pool as a singleton, rather than create it one at a time by executing the method above. It’s easy to run out of production server resources
  • The maximum number of threads in the thread pool must be determined when the thread pool is created, and the number of threads must be set based on service requirements
  • The waiting queue size of the thread pool can be set according to business requirements and specific problems. (Generally, unbounded queues are not allowed. In case of blocking, unbounded queues may consume all resources of the service.)

4. To summarize

Being in awe of every line of code makes it more efficient, concise, and elegant. If you’re just going to use it for some technology, and you don’t know why, it’s better to implement it in the dumbest way possible. At least it won’t cause program problems or service unavailability. Write a simple simulation program to verify your conjecture on some uncertain questions or questions.