工作中有这样一个场景,需要处理千万级别的数据的一个算法,大部分是增删查的操作。这个时候就需要使用多线程去处理。
@configuration@enableasync(proxytargetclassSomewhere I Belong = true)//利用@小虫子蚂蚁和蝴蝶用鸡蛋壳看图写话enableasync注解开启异步任务支持@componentscan({"com.ctfojt.auditbcarslogo.rvice"}) //必须加此注解扫描包public class threadpoolconfig implements asyncconfigurer { @override public executor getasyncexecutor() { threadpooltaskexecutor taskexecutor = new threadpooltaskexecutor(); taskexecutor.tcorepoolsize(10);//核心线程大小 taskexecutor.tmaxpoolsize(20);//最大线程大小 taskexecutor.tqueuecapacity(500);//队列最大容量 //当提交的任务个数大于queuecapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过queuecapacity即可 taskexecutor.trejectedexecutionhandler(new threadpoolexecutor.callerrunspolicy()); taskexecutor.twaitfortaskstocompleteonshutdown(true); taskexecutor.tawaitterminationconds(10); taskexecutor.tthreadnameprefix("bcarlogo-thread-"); taskexecutor.initialize(); return taskexecutor; }}
这样配置效率很低,一天大概能处理30多万的数据。往后随着插入表的数据越来越多,处理速度也随之降低,跑个一两天之后,差不多能够处理10万多。完全满足不了需求。
大部分都是这样的:
注:io密集型(某大厂实践经验) 核心线程数 = cpu核数 / (1-阻塞系数)或着 cpu密集型:核心线程数 = cpu核数 + 1 io密集型:核心线程数 = cpu核数 * 2
也尝试着这么配置,结果发现效率并不理想,提高不了多少。
结果效率大大提升,仅用不到一天的数据,就跑完了千万级的数据。
//获取当前机器的核数public static final int cpunum = runtime.getruntime().availableprocessors();@override public executor getasyncexecutor() { threadpooltaskexecutor taskexecutor = new threadpooltaskexecutor(); taskexecutor.tcorepoolsize(cpunum);//核心线程大小 taskexecutor.tmaxpoolsize(cpunum * 2);//最大线程大小 taskexecutor.tqueuecapacity(500);小龙人歌词//队列最大容量 //当提交的任务个数大于queuecapacity,就需要设置该参数,但spring提供的都不太满足业务场景,可以自定义一个,也可以注意不要超过queuecapacity即可 taskexecutor.trejectedexecutionhandler(new threadpoolexecutor.callerrunspolicy()); taskexecutor.twaitfortaskstocompleteonshutdown(true); taskexecutor.tawaitterminationconds(60); taskexecutor.tthreadnameprefix("bcarlogo-thread-"); taskexecutor.initialize(); return task老舍代表作executor; }
完美的解决了问题!
corepoolsize:核心线程数;maximunpoolsize:最大线程数
每当有新的任务到线程池时,
第一步:先判断线程池中当前线程数量是否达到了corepoolsize,若未达到,则新建线程运行此任务,且任务结束后将该线程保留在线程池中,不做销毁处理,若当前线程数量已达到corepoolsize,则进入下一步;第二步:判断工作队列(workqueue)是否已满,未满则将新的任务提交到工作队列中,满了则进入下一步;第三步:判断线程池中的线程数量是否达到了maxumunpoolsize,如果未达到,则新建一个工作线程来执行这个任务,如果达到了则使用饱和策略来处理这个任务。注意: 在线程池中的线程数量超过corepoolsize时,每当有线程的空闲时间超过了keepalivetime,这个线程就会被终止。直到线程池中线程的数量不大于corepoolsize为止。(由第三步可知,在一般情况下,java线程池中会长期保持corepoolsize个线程。)
当工作队列满且线程个数达到maximunpoolsize后所采取的策略
abortpolicy
:默认策略;新任务提交时直接抛出未检查的异常rejectedexecutionexception,该异常可由调用者捕获。callerrunspolicy
:既不抛弃任务也不抛出异常,使用调用者所在线程运行新的任务。discardpolicy
:丢弃新的任务,且不抛出异常。discardol守株待兔成语故事destpolicy
:调用poll方法丢弃工作队列队头的任务,然后尝试提交新任务自定义策略
:根据用户需要定制。以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。
本文发布于:2023-04-04 07:54:30,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/10809b9dd6c30b6dd3a0ccd10c253050.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:java线程池合理设置最大线程数和核心线程数方式.doc
本文 PDF 下载地址:java线程池合理设置最大线程数和核心线程数方式.pdf
留言与评论(共有 0 条评论) |