Thread pool ThreadPoolExecutor summary

Keywords: Java JUC

Thread pool ThreadPoolExecutor

  • What is it: Workers' sweatshop
  • What's the use: reduce resource consumption and facilitate thread management
  • How to play: play with your new thread pool

Thread pool principle

Working principle of thread pool (advantages and disadvantages)

When there is no thread pool, compare it with the wired process pool. It solves the problem of resource allocation, the idea of pooling, maximizes income, minimizes risk, and unifies the way of resource management.

Five statuses of thread pool (run, shutdown, Stop, dying, terminated)

Thread pool state transition (changes in shutdown, shutdown now and workerQueue)

7 parameters (core, max, keepAliveTime, unit, workerQueue, factory, rejectHandler)

4 reject policies (ACDD)

I don't know what the above is: please go out and turn left:
https://blog.csdn.net/weixin_43801418/article/details/120396484

Basic method

Construction method - > 7 parameters

Small function functions, many of which operate around ctl

runStateOf,workerCountOf,ctlOf

Worker wrapper class, run()

Core method

execute

Submit task process: method of receiving task

1,The task is commond,A request comes in the thread pool
2,Judge whether the current number of workers is less than core,call addWorker(command, true)
	Successful, return directly
	Failed. It may be a concurrency problem. Other threads have completed this task; or Thread state change, non running state
3,Try to put workerQueue
	1)Status modified non running,Remove the current task and execute the reject policy
		Success: the task has not been consumed (still in use) workerQue Medium)
		Failed: after submitting, the shutdown() shutdownNow()Before, it is processed by the threads in the thread pool.
	2)still running State, judgment ctl The number of threads is 0, addWorker,At least one thread is working
4,Last direct addWorker(command, false),use max judge
	Failed: reject(command)

Is worker an instance object or a task?

addWorker

Add new worker s and new methods

Part I: two for spins to judge the thread status and the number of worker s, and the process of taking tokens

Part II: new Worker(firstTask); For incoming tasks, the number of threads is managed by the thread pool itself

In the shutdown state, there are tasks in the workerQueue task queue, and the tasks to be executed are null = > new workers can be added to execute threads

1,Judgment status:
	1)running state  √
	2)shutdown,workerQueue Not empty, firstTask Empty  √
2,judge woker Number, workerCount
	1)wc exceed capacity,exceed core or max  => return false
	2)wc with cas Method plus 1 to try to get a token
		Success: get the token and go to the next process
		Failed: the current thread status changes and needs to be retried (re judge whether the status meets the requirements)
3,new Worker(firstTask),There are threads, and we will do this later worker Judge whether it is legal.
4,use mainLock Global lock start
	Judge whether the wire pool is① running Status② shutdown And the task queue is alive and nothing new comes in.
	no problem workers Set Join this worker Go in and work.
	Release lock
5,last worker join set The aftermath of failure. mainLock
	1)yes ctl Minus one
	2)set take worker Clear out

runWorker

worker startup

1,initialization wt,task,Exclusive lock lock(-1 -> 0)
2,getTask from workQueue Apply for task
3,open lock,
      1)Judging that the thread is dead, STOP After that, the marking thread is interrupted
      2)Hook methods, like transactions, can implement pre notification by subclasses
          Perform tasks, run
      3)Hook methods, like transactions, can implement subsequent notifications by subclasses
4,Untie lock(release worker Non reentrant lock)
5,If there are exceptions, handle them uniformly, otherwise exit normally

be careful:

1. processWorkerExit() method, destroy the thread.

2. The while loop continuously obtains the task through the getTask() method.

3. Threads that do not work are blocked unless the thread pool is ready to end

getTask

1. Obtain the task process from the workerQueue; 2. Also responsible for recycling threads

Generally, you can get the task normally. In several cases, you can't get the desired result (null)

return null There are several situations:( State,workerCount)
    1,rs >= STOP 
    2,shutdown And workerQueue Empty
    3,wc > max
    4,wc > core && overtime
    
Timeout factor:
    allowCoreTimeOut
    cas Mode reclaim thread( wc Too large, current task timed out)

processWorkerExit

When the worker exits the process, it will always be called in runWorker.

Because there are many possibilities of thread destruction, the thread pool also needs to judge what caused the destruction, whether to change the current state of the thread pool, and whether to reassign threads according to the new state.

private void processWorkerExit(Worker w, boolean completedAbruptly) {
1,normal or Abnormal exit
    1)Abnormal exit: ctl-1
    2)Normal exit: take mainLock;set Remove the worker,Record complete task quantity
2,tryTerminate();  
    Enter the logic to close the thread pool
3,Exit normally, leaving the last thread for the thread
        1)minimum worker The number can be at least one worker You can continue to work
        2)workerCountOf(c) >= min Then it is safe to continue the exit logic
4,Abnormal exit: because there are many possibilities of thread destruction, the thread pool also needs to judge what caused the destruction, whether to change the current state of the thread pool, and whether to reassign threads according to the new state.

shutdown & shutdownNow

Thread shutdown process

shutdown does only two things

1) Modify the thread pool status to shutdown

2) Mark all idle workers as interrupted and tell them it's time to stop work

1,advanceRunState: adopt cas Force setting status to SHUTDOWN
2,Acquired worker
3,Interrupt idle thread
	plus mainLock
    	Traverse all worker
    	Lock them separately and give them to all getTask Medium blocking (in take/poll Status) worker Make interrupt mark
	release mainLock
4,Release global lock mainLock
5,tryTerminate();

shutdownNow is just an additional return method to take out the unprocessed tasks in the workQueue for processing

1,advanceRunState: adopt cas Force setting status to SHUTDOWN
2,Acquired worker
3,Interrupt idle thread
    plus mainLock
        Traverse all worker
    	Lock them separately and give them to all getTask Medium blocking (in take/poll Status) worker Make interrupt mark
    release mainLock
4,tasks = drainQueue();
5,Release global lock mainLock
6,tryTerminate();
7,return tasks;

tryTerminate

1,Entry spin
    1)running
    2)Another thread is TIDYING -> TERMINATED
    3)shutdown And workQueue Not empty runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()

2,Ways to interrupt lazy employees.
    if (workerCountOf(c) != 0) { Execute as long as there are employees in the thread pool interruptIdleWorkers

3,the last one worker be responsible for
        0,Lock mainLock
        1,Set status to TIDYING
        2,Set status to TERMINATED
        3,termination.signalAll();  Notify the external thread to wait for the thread pool to become terminated state
        0,release mainLock

reference resources

https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html

Posted by t_machine on Fri, 01 Oct 2021 17:50:40 -0700