“This is the 14th day of my participation in the August Gwen Challenge

Play with Java thread pools:

  • Play with Java thread pool 1: How ThreadPoolExecutor executes
  • Playing with Java thread pool 2: The use of ThreadPoolExecutor
  • Play with Java thread pool 3: Executor parsing for the top-level interface of thread pool design

Why use thread pools

In the real development is not manually to new a thread out of use, Alibaba’s Java development manual also said that do not manually create threads, to use thread pool. Almost any program that needs to be executed asynchronously or concurrently can use thread pools. There are three benefits to using thread pools:

  • Reduce resource consumption: There are already created threads in the thread pool. By reusing these threads, you can reduce the cost of thread creation and destruction.
  • Improved response time: When a task is completed, it can be executed immediately without creating a thread pool.
  • Improve thread manageability: threads are a valuable resource, heavyweight. It consumes system resources and reduces system stability. Using thread pools allows unified management, tuning, and monitoring of threads.

Second, the processing flow of thread pool

When a new task is submitted to the thread pool, the thread pool process is as follows:

Thread pool Determines whether all threads in the core thread pool are executing tasks. If not, a new worker thread is created to execute the task. If all the threads in the core thread pool are executing tasks, the next process goes on.

2. The thread pool determines whether the work queue is full. If the work queue is not full, the newly submitted task is stored in the work queue. If the work queue is full, it goes to the next process. Thread pool Checks whether all the threads in the thread pool are working. If not, a new worker thread is created to execute the task. If it is full, the saturation policy is assigned to handle the task.

The diagram below:

The Java thread pool class is ThreadPoolExecutor, which implements the execute method. The main execute process is as follows:

In general, ThreadPoolExecutor’s execute method looks like this:

1. If the current thread pool has fewer threads running than corePoolSize, create a thread to execute the submitted task. (This operation requires a global lock.)

2. If the current thread pool is running threads equal to or greater than corePoolSize, the submitted task will be placed in BlockingQueue.

If the BlockingQueue is full, create a new thread for the task (this requires a global lock).

4. If the number of threads in the thread pool exceeds maximumPoolSize, the submitted task will be rejected and the rejection policy will be implemented

Execute method source code parsing

public void execute(Runnable command) {
    	// If the current task is empty, throw a null pointer exception
        if (command == null)
            throw new NullPointerException();
    	// Get the combination of the current thread pool state and the number of threads variable
        int c = ctl.get();
    	// If the current thread count is smaller than the core thread pool size, the thread is created and the current task is executed
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
    	// If the thread pool is in the RUNNING state, add the task to the blocking queue
        if (isRunning(c) && workQueue.offer(command)) {
            // Double check
            int recheck = ctl.get();
            // If the current thread pool state is not RUNNING, the task is removed from the queue and the thread pool reject policy is executed
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // Create a thread if the current thread pool is empty
            else if (workerCountOf(recheck) == 0)
                addWorker(null.false);
        }
    	If the queue is full, a new thread is added, and if the new thread fails, the thread pool rejection policy is executed
        else if(! addWorker(command,false))
            reject(command);
    }
Copy the code