当前位置:网站首页>Elegant custom ThreadPoolExecutor thread pool
Elegant custom ThreadPoolExecutor thread pool
2022-06-24 21:52:00 【Jingling cat】
summary
java It is often necessary to Use multithreading to handle some business
, very Not recommended
Use Inherit Thread
perhaps Realization Runnable Interface
The way to Create thread
, like that Creating and destroying threads is bound to consume resources 、 Thread context switching problem
. meanwhile Creating too many threads can also lead to the risk of resource exhaustion
, This is the time It is reasonable to introduce thread pool , Facilitate the management of thread tasks
.
java The related classes related to thread pool in jdk 1.5
At the beginning java.util.concurrent
In bag , Several core classes and interfaces involved include :Executor、Executors、ExecutorService、ThreadPoolExecutor、FutureTask、Callable、Runnable etc.
JDK Automatically create thread pool
Several methods of are encapsulated in Executors Tool class
in :
newFixedThreadPool
new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())
Set up corePoolSize=maxPoolSize
,keepAliveTime=0( This parameter has no effect at this time )
, Unbounded queue
, Mission
Sure Unlimited placement
, When Too many requests ( The task processing speed cannot keep up with the task submission speed, resulting in request accumulation ) It may cause excessive memory consumption or directly cause OOM abnormal .
newSingleThreadExector
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), var0)
basic Same as newFixedThreadPool
, however Set the number of threads to 1
, Single thread
, Disadvantages and newFixedThreadPool Agreement
newCachedThreadPool
new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue())
corePoolSize=0,maxPoolSize For a large number
, Synchronous handover queue , in other words Do not maintain resident threads ( Core thread )
, Each time a request is made, a new thread is created directly to handle the task
, also Do not use queue buffering
, Meeting Automatically reclaim redundant threads
, because take maxPoolSize Set to Integer.MAX_VALUE, When there are many requests, it is possible to create too many threads , Lead to exhaustion of resources OOM
newScheduledThreadPool
new ThreadPoolExecutor(var1, 2147483647, 0L, TimeUnit.NANOSECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue())
Support Execute periodically at a fixed time
, Pay attention to the Using a delay queue
, The disadvantages are the same as newCachedThreadPool Agreement
So the above says to use Executors The thread pool created by the tool class has hidden dangers , So how to use it to avoid this hidden danger ? What is the most elegant way to use a thread pool ?
How is it reasonable for a production environment to configure its own thread pool ? We need to take the right medicine , Create your own thread factory class , Set key parameters flexibly .
ThreadPoolExecutor class
want Custom thread pool
, Need to use ThreadPoolExecutor class
ThreadPoolExecutor
Construction method of class ,7 Parameters
public ThreadPoolExecutor(int coreSize,int maxSize,long KeepAliveTime,TimeUnit unit,BlockingQueue queue,ThreadFactory factory,RejectedExectionHandler handler)
corePoolSize: Number of core threads , It is also the number of resident threads in the thread pool
When the thread pool is initialized, there are no threads by default , When the task comes, it starts to create a thread to execute the task
maximumPoolSize: Maximum number of threads , Some non core threads may be added to the number of core threads
It should be noted that only when workQueue The queue is not created until it is full More than corePoolSize The thread of
( The total number of threads in the thread pool does not exceed maxPoolSize)
keepAliveTime: Non core thread Of free time exceed keepAliveTime Will be Automatically terminate recycling
Pay attention to when corePoolSize=maxPoolSize when ,keepAliveTime Parameters don't work ( Because there are no non core threads )
unit: keepAliveTime Time unit of
workQueue: The queue used to hold the task , Can be unbounded 、 bounded 、 Synchronous handover is one of three queue types
When the number of worker threads in the pool Greater than corePoolSize when , At this time, the new task will be put in the queue
threadFactory: Create a factory class for threads , By default Executors.defaultThreadFactory(), You can also use guava Library ThreadFactoryBuilder To create
handler: The thread pool cannot continue to receive tasks ( The queue is full and the number of threads reached maximunPoolSize ) Saturation strategy at
Values are AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy
Thread pool configuration related
Setting the thread pool size
Be clear about our needs Computationally intensive
still IO intensive
Computationally intensive
Applications need to be A lot of CPU Computing resources
, In multicore CPU Time , We want to Let every one CPU The core is involved in the calculation
, take CPU Take full advantage of the performance
, This is not a waste of server configuration , If Running a single threaded program on a very good server configuration would be a huge waste
. For computationally intensive applications , Entirely on CPU To work , So in order for it to fully play its advantages , Avoid excessive thread context switching , The ideal solution is :
Number of threads = CPU Check the number + 1, You can also set it to CPU Check the number *2, But also look at JDK Version and CPU To configure ( Server's CPU Have hyper-threading )
General Settings
CPU * 2 that will do
IO intensive
Most of the current development is WEB application
, involves A lot of network traffic
, More Than This , With the database , The interaction with the cache is also involved IO, Once occurred IO, The thread will be in a waiting state , When IO end , When the data is ready , The thread will continue execution
.
about IO Intensive application , We can Set more threads in the thread pool
, So that we can Waiting for the IO During this period of time , Threads can do other things , Improve the efficiency of concurrent processing
. So the amount of data in this thread pool can be set arbitrarily ? Of course not , Please do remember , Thread context switching comes at a cost . At present, a set of formulas is summarized , about IO Intensive application :
Number of threads = CPU The core number /(1- Block coefficient ) The blocking coefficient is usually zero 0.8~0.9 Between , Can also take 0.8 perhaps 0.9.
To paraphrase formula , about Dual core CPU
Come on , It's more The ideal number of threads is 20
, Of course, none of this is absolute , It needs to be adjusted according to the actual situation and the actual business :final int poolSize = (int)(cpuCore/(1-0.9))
Thread pool related parameter configuration
One 、 A certain Do not select configuration items without upper limit
.
That's why Not recommended Executors Method to create a thread in
.
for example ,Executors.newCachedThreadPool
The settings and Setting of unbounded queue
Because of some unexpected circumstances , A system exception will occur in the thread pool
, A condition that causes a thread explosion or a task queue to swell , Running out of memory leads to system crashes and exceptions
It is recommended to use a custom thread pool to avoid this problem , This is also the first principle in using the thread pool specification !
Two 、 Set the number of threads appropriately 、 And thread idle recovery time
according to Set the specific task execution cycle and time
, Avoid frequent recycling and creation
, Although we use thread pools for Improve system performance and throughput , But you also have to think about the stability of the system
, Otherwise it would be very troublesome to have unexpected problems !
3、 ... and 、 According to the actual scenario , Choose a rejection strategy that works for you
Make compensation , Don't mess with JDK Automatic compensation mechanism supported
! Try to use a custom rejection policy to cover the cost
Four 、 Thread pool rejection policy , Custom rejection policies can be implemented RejectedExecutionHandler Interface
JDK The default rejection strategy is as follows :
AbortPolicy: Throwing an exception directly prevents the system from working properly .
CallerRunsPolicy: As long as the thread pool is not closed , The policy is directly in the caller thread , Run the currently discarded task .
DiscardOldestPolicy: Discard the oldest request , Try to commit the current task again .
DiscardPolicy: Discard unmanageable tasks , Do not give any treatment .
utilize Hook
utilize Hook
, leave Thread pool execution trace
:
ThreadPoolExecutor
Provides protected Type of hook method that can be overridden
, Allows the user to do something before and after the task is executed
. We can use it to achieve, for example initialization ThreadLocal、 Collect statistics 、 Such as logging operations
. This kind of Hook
Such as beforeExecute
and afterExecute
. in addition One more Hook Can be used to allow the user to insert logic when the task is completed , Such as rerminated
If hook Method execution failed
, be The execution of the internal worker thread will fail or be interrupted
We can use beforeExecute and afterExecute
Come on Record some running conditions before and after the thread
, You can also directly record the state after the completion of the run ELK Isolog system .
Close thread pool
When The thread pool is no longer referenced
also The number of worker threads is 0
When , The thread pool will be terminated
. We can call shutdown To manually terminate the thread pool
. If we Forget to call shutdown, For thread resources to be freed
, We You can also use keepAliveTime
and allowCoreThreadTimeOut
To achieve the goal !
Of course , A safe way
It's using virtual machine Runtime.getRuntime().addShutdownHook
Method , Manually call the thread pool closure method
Things that can be optimized
Set the threads in the thread pool to Daemon
In general , After closing the thread pool
, The thread pool will End the thread by itself
. but For some of their own camouflage or direct new Thread() This thread of , Will still block the process from shutting down
according to ,java Process shutdown determination method
, When There is only Daemon Threads
when , The process will shut down normally
. therefore , Suggest these All non primary threads are set to daemon, That is, process shutdown will not be blocked
Correct naming Thread
When using thread pools , Usually Accept ThreadFactory object
, Come on Controls how to create thread
. stay java Self contained ExecutorService
when , If This parameter is not set
, will Use default DefaultThreadFactory
. The effect is , You will be in the stack list , See a bunch of pool-x-thread-y,
In actual use jstack when , It is impossible to see the group to which each of these threads belongs , And the specific role .
Discard recurring tasks that are no longer available
In general , Use java Self contained ScheduledThreadPoolExecutor
, call scheduleAtFixedRate And scheduleWithFixedDelay
All will Set the task to periodic (period)
. stay Thread pool shutdown
when , These tasks can be discarded directly ( By default ).
But if Use schedule When adding long-term tasks
, Thread pool
will Because it is not a periodic task, the corresponding thread will not be closed
Such as spring In the system TriggerTask( Include CronTask)
, To carry out Scheduled tasks
, They all end up being adopt schedule To achieve scheduling
, And in When a single task is completed , Again schedule To perform the next task
. This approach would be considered not period. therefore , When using this scheduling method , Although when the container is closed , Yes shutdown Method , But corresponding to the bottom ScheduledExecutorService It still won't shut down successfully ( Although all States have been set )
. The end result is , You will see one that is already in shutdown Thread pool for state , But the thread is still running ( Status as wait Mission ) The situation of
To solve this problem ,java Provide an additional setting parameter executeExistingDelayedTasksAfterShutdown,
This value defaults to true, namely shutdown after , Still carry out
. It can be done by When defining a thread pool, set it to false, That is, after the thread pool is closed , Don't run these deferred tasks anymore
边栏推荐
- leetcode1863_2021-10-14
- About transform InverseTransformPoint, transform. InverseTransofrmDirection
- The most important thing at present
- Functional analysis of ebpf tracepoint
- 【吴恩达笔记】机器学习基础
- Blender FAQs
- 虚拟机CentOS7中无图形界面安装Oracle(保姆级安装)
- 使用Adb连接设备时提示设备无权限
- Object.defineProperty和Reflect.defineProperty的容错问题
- openGauss内核:简单查询的执行
猜你喜欢
Byte software testing basin friends, you can change jobs. Is this still the byte you are thinking about?
Wireshark packet capturing skills summarized by myself
应用实践 | 海量数据,秒级分析!Flink+Doris 构建实时数仓方案
Make tea and talk about heroes! Leaders of Fujian Provincial Development and Reform Commission and Fujian municipal business office visited Yurun Health Division for exchange and guidance
福建省发改委福州市营商办莅临育润大健康事业部指导视察工作
LeetCode-513. 找树左下角的值
EasyBypass
Blender's simple skills - array, rotation, array and curve
[camera Foundation (I)] working principle and overall structure of camera
多线程收尾
随机推荐
socket(2)
leetcode_1470_2021.10.12
Memcached comprehensive analysis – 3 Deletion mechanism and development direction of memcached
Remove the screen recording reminder (seven cattle cloud demo)
WMI and PowerShell get TCP connection list
Transport layer UDP & TCP
多线程收尾
TDengine可通过数据同步工具 DataX读写
PKI notes
Pattern recognition - 9 Decision tree
Bld3 getting started UI
字节的软件测试盆友们你们可以跳槽了,这还是你们心心念念的字节吗?
Analyse complète Memcached – 2. Comprendre le stockage de mémoire pour Memcached
ST表+二分
Unity about conversion between local and world coordinates
Memcached comprehensive analysis – 2 Understand memcached memory storage
suspense组件和异步组件
关于Unity中的transform.InverseTransformPoint, transform.InverseTransofrmDirection
66 pitfalls in go programming language: pitfalls and common errors of golang developers
建木持续集成平台v2.5.0发布