Thread pool tuning of Java multithreading

Thread pool tuning of Java multithreading

 

default allocation

 

  • corePoolSize=1
  • queueCapacity=Integer.MAX_VALUE
  • maxPoolSize=Integer.MAX_VALUE
  • keepAliveTime=60s
  • allowCoreThreadTimeout=false
  • rejectedExecutionHandler=AbortPolicy()

shortcoming

 

  • The initial value of corePoolSize core thread is 1 too little
  • The queueCapacity and maxPoolSize are set so large, I am afraid that there are too many threads and the system can't stand it
  • The rejectedExecutionHandler can be changed

 

 

 

How to optimize

 

Need to decide based on several values

 

  • tasks : the number of tasks per second, assuming 500~1000
  • taskcost: the time spent on each task, assuming 0.1s
  • responsetime: the maximum response time that the system allows to tolerate, assuming 1s

 

do some calculations

 

corePoolSize = How many threads per second are required? 

 

  • threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 threads. corePoolSize setting should be greater than 50
  • According to the 8020 principle, if 80% of the tasks per second are less than 800, then the corePoolSize can be set to 80

 

queueCapacity = (coreSizePool/taskcost)*responsetime

 

  • It can be calculated that queueCapacity = 80/0.1*1 = 80. It means that the threads in the queue can wait for 1s, and if it exceeds, a new thread needs to be opened to execute
  • Remember that it cannot be set to Integer.MAX_VALUE, so the queue will be very large, and the number of threads will only remain at the corePoolSize size. When the task increases sharply, new threads cannot be opened for execution, and the response time will increase sharply.

 

maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)

 

  • Calculated to get maxPoolSize = (1000-80)/10 = 92
  • (Maximum number of tasks - queue capacity) / processing capacity per thread per second = maximum number of threads

 

rejectedExecutionHandler : It is determined according to the specific situation. The task is not important and can be discarded. If the task is important, some buffering mechanisms should be used to process it.

 

 

keepAliveTime and allowCoreThreadTimeout are usually satisfied by default

 

        The above are all ideal values, which should be determined according to the performance of the machine in actual situations. If the cpu load of the machine is full before the maximum number of threads is reached, you need to upgrade the hardware (hehe) and optimize the code to reduce the task cost to deal with it.

 

 

 

 

some experience

 

dev configuration

 

  • corePoolSize=20
  • queueCapacity=100
  • maxPoolSize=150
  • keepAliveTime=300s
  • waitForTasksToCompleteOnShutdown=true, finish the task first and then shutdown
  • rejectedExecutionHandler=CallerRunsPolicy(), let the calling thread continue to complete the task

 

prod configuration

 

  • corePoolSize=20
  • queueCapacity=200
  • maxPoolSize=500
  • keepAliveTime=300s
  • waitForTasksToCompleteOnShutdown=true, finish the task first and then shutdown
  • rejectedExecutionHandler=CallerRunsPolicy(), let the calling thread continue to complete the task

 

suggestion

 

     In practice, it is recommended to do a stress test first, try to use the ideal number of threads during the test, check the upper limit of threads, and then gradually adjust the thread pool.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326515484&siteId=291194637