当前位置:网站首页>Elegant custom ThreadPoolExecutor thread pool
Elegant custom ThreadPoolExecutor thread pool
2022-06-27 14:23:00 【It takes time for fish to find water】
summary
java Multithreading is often used to handle some business , Inheritance alone is highly discouraged Thread Or realize Runnable Interface to create threads , In that case, it is bound to cost resources to create and destroy threads 、 Thread context switching problem . At the same time, creating too many threads may also lead to the risk of resource exhaustion , It is reasonable to introduce thread pool at this time , 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 Several ways to automatically create thread pools are encapsulated in Executors In the tool class :
newFixedThreadPool
The construction method used is
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 , Tasks can be put into , When there are 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
The construction method used is
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), var0)
Basically the same newFixedThreadPool, But set the number of threads to 1, Single thread , Disadvantages and newFixedThreadPool Agreement .
newCachedThreadPool
The construction method used is
new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue())
corePoolSize=0,maxPoolSize For a large number , Synchronous handover queue , That is, resident threads are not maintained ( Core thread ), Each time a request is made, a new thread is created directly to handle the task , Queue buffering is also not used , Will automatically recycle redundant threads , Because will 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
The construction method used is
new ThreadPoolExecutor(var1, 2147483647, 0L, TimeUnit.NANOSECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue())
Support regular periodic execution , Note that you are 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 ?
The production environment needs to suit the case , Create your own thread factory class , Set key parameters flexibly .
ThreadPoolExecutor class
To customize the thread pool , Need to use ThreadPoolExecutor class .
ThreadPoolExecutor Construction method of class :
public ThreadPoolExecutor(int coreSize,int maxSize,long KeepAliveTime,TimeUnit unit,BlockingQueue queue,ThreadFactory factory,RejectedExectionHandler handler)
The above construction method has seven parameters , The meanings of these seven parameters are :
- 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
workQueueMore than... Will be created when the queue is fullcorePoolSizeThe thread of ( The total number of threads in the thread pool does not exceedmaxPoolSize) - keepAliveTime: The idle time of non core thread exceeds
keepAliveTimeWill be automatically terminated and recycled , Pay attention to whencorePoolSize=maxPoolSizewhen ,keepAliveTimeParameters don't work ( Because there are no non core threads ); - unit:
keepAliveTimeTime 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 is greater than
corePoolSizewhen , 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 LibraryThreadFactoryBuilderTo 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 areAbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy
Thread pool configuration related
Setting the thread pool size
First of all, we should clarify whether our requirements are computing intensive or IO intensive , Only to understand this point , We can better limit the number of thread pools .
Computationally intensive
As the name implies, the application needs a lot CPU Computing resources , In multicore CPU Time , We're going to make each 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 , What a waste it would be to have a single threaded program running on a very good server configuration . 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 development we're doing right now is WEB application , A lot of network traffic is involved , 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 .
So you can see it here , about IO Intensive application , We can set the number of threads in the thread pool a few more , This will keep you waiting 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 , The dual - CPU Come on , The ideal number of threads 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
Be sure not to select configuration items that have no upper limit .
Is that why it's not recommended Executors Method to create a thread in .
for example ,Executors.newCachedThreadPool Is set up with unbounded queue because of some unexpected situation , 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 !
second , Set the number of threads appropriately 、 And thread idle recovery time ,
According to the specific task execution cycle and time to set , Avoid frequent recycling and creation , Although we use thread pools to 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 !
Third , 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 !
Fourth , 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 the 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 do things like initialization with it ThreadLocal、 Collect statistics 、 Such as logging operations . This kind of Hook Such as beforeExecute and afterExecute. There's another one Hook Can be used to allow the user to insert logic when the task is completed , Such as rerminated .
If hook Method execution failed , The execution of the internal worker thread will fail or be interrupted .
We can use beforeExecute and afterExecute To record some running 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 and the number of worker threads is 0 When , The thread pool will be terminated . We can also call shutdown To manually terminate the thread pool . If we forget to call shutdown, For thread resources to be freed , We can also use keepAliveTime and allowCoreThreadTimeOut To achieve the goal !
Of course , The safe way is to use a 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 its threads 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 Thread time , The process will shut down normally . therefore , It is recommended that these non primary threads be set to daemon, That is, process shutdown will not be blocked .
Correct naming Thread
When using thread pools , Generally, I will accept ThreadFactory object , To control how to create thread. stay java Self contained ExecutorService when , If this parameter is not set , The 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 Will set the task to be periodic (period). When the process pool is closed , These tasks can be discarded directly ( By default ). But if schedule When adding long-term tasks , The thread pool will not close the corresponding thread because it is not a periodic task
Such as spring In the system TriggerTask( Include CronTask), To perform scheduled tasks , All of them are finally passed schedule To achieve scheduling , And after 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 . You can define a thread pool by setting it to false, That is, after the thread pool is closed , Don't run these deferred tasks anymore .
Copyright notice : This paper is about CSDN Blogger 「chun_soft」 The original article of , follow CC 4.0 BY-SA Copyright agreement , For reprint, please attach the original source link and this statement .
https://blog.csdn.net/ztchun/article/details/116602405
边栏推荐
- Redis 主从复制、哨兵模式、Cluster集群
- my.ini文件配置
- NAACL 2022 | TAMT:通过下游任务无关掩码训练搜索可迁移的BERT子网络
- [an Xun cup 2019]attack
- A brief analysis of the differences between domestic and foreign e-commerce
- 高德地图IP定位2.0备份
- Tsinghua & Shangtang & Shanghai AI & CUHK proposed Siamese image modeling, which has both linear probing and intensive prediction performance
- CCID Consulting released the database Market Research Report on key application fields during the "14th five year plan" (attached with download)
- High efficiency exponentiation
- Web chat room system based on SSM
猜你喜欢

American chips are hit hard again, and another chip enterprise after Intel will be overtaken by Chinese chips

国产数据库乱象

【微服务|Sentinel】热点规则|授权规则|集群流控|机器列表

At a time of oversupply of chips, China, the largest importer, continued to reduce imports, and the United States panicked

Redis persistence

【mysql进阶】MTS主从同步原理及实操指南(七)

基于WEB平台的阅读APP设计与实现
机械硬盘和ssd固态硬盘的原理对比分析

海量数据!秒级分析!Flink+Doris构建实时数仓方案

隱私計算FATE-離線預測
随机推荐
PR second training notes
招标公告:暨南大学附属第一医院Oracle数据库维保服务采购
Redis persistence
Longest substring without repeated characters (Sword finger offer 48)
The second part of the travel notes of C (Part II) structural thinking: Zen is stable; all four advocate structure
Make a ThreadLocal (source code) that everyone can understand
Kyndryl与Oracle和Veritas达成合作
[xman2018 qualifying] pass
[advanced MySQL] MTS master-slave synchronization principle and Practice Guide (7)
Leetcode 724. 寻找数组的中心下标(可以,一次过)
海量数据!秒级分析!Flink+Doris构建实时数仓方案
Pisa-Proxy 之 SQL 解析实践
Use GCC to generate an abstract syntax tree "ast" and dump it to Dot file and visualization
【mysql进阶】MTS主从同步原理及实操指南(七)
Julia1.1 installation instructions
Design and implementation of reading app based on Web Platform
enable_ if
Step by step expansion of variable parameters in class templates
Acwing game 57
NAACL 2022 | TAMT:通过下游任务无关掩码训练搜索可迁移的BERT子网络