纠纷奇闻社交美文家庭
投稿投诉
家庭城市
爱好生活
创业男女
能力餐饮
美文职业
心理周易
母婴奇趣
两性技能
社交传统
新闻范文
工作个人
思考社会
作文职场
家居中考
兴趣安全
解密魅力
奇闻笑话
写作笔记
阅读企业
饮食时事
纠纷案例
初中历史
说说童话
乐趣治疗

SpringBoot参数搜一堆资料还是不会配,我花一天测试换

6月2日 多上心投稿
  案例1、编写案例
  自定义一个线程池,并加上初始配置。
  核心线程数10,最大线程数50,队列大小200,自定义线程池名称前缀为myexecutor,以及线程池拒绝策略为AbortPolicy,也是默认策略,表示直接放弃任务。packagecom。example。executor。importlombok。extern。slf4j。Slf4j;importorg。springframework。context。annotation。Bimportorg。springframework。context。annotation。Cimportorg。springframework。scheduling。annotation。EnableAimportorg。springframework。scheduling。annotation。EnableSimportorg。springframework。scheduling。concurrent。ThreadPoolTaskEimportjava。util。concurrent。Eimportjava。util。concurrent。ThreadPoolEConfigurationEnableAsyncEnableSchedulingSlf4jpublicclassAsyncConfiguration{自定义线程池Bean(namemyExecutor)publicExecutorgetNetHospitalMsgAsyncExecutor(){log。info(CreatingmyExecutorAsyncTaskExecutor);ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(10);executor。setMaxPoolSize(50);executor。setQueueCapacity(200);executor。setThreadNamePrefix(myexecutor);拒绝策略:直接拒绝抛出异常executor。setRejectedExecutionHandler(newThreadPoolExecutor。AbortPolicy());}}
  接下来,我们写一个异步服务,直接使用这个自定义线程池,并且模拟一个耗时5秒的发消息业务。packagecom。example。executor。importlombok。extern。slf4j。Slf4j;importorg。springframework。scheduling。annotation。Aimportorg。springframework。stereotype。Simportjava。util。concurrent。TimeUp异步服务author福隆苑居士,公众号:【Java分享客栈】since202243011:41ServiceSlf4jpublicclassAsyncService{模拟耗时的发消息业务Async(myExecutor)publicvoidsendMsg()throwsInterruptedException{log。info(〔AsyncService〕〔sendMsg〕发消息。。。。);TimeUnit。SECONDS。sleep(5);}}
  然后,我们写一个TestService,使用Hutools自带的并发工具来调用上面的发消息服务,并发数设置为200,也就是同时开启200个线程来执行业务。packagecom。example。executor。importcn。hutool。core。thread。ConcurrencyTimportcn。hutool。core。thread。ThreadUimportlombok。extern。slf4j。Slf4j;importorg。springframework。stereotype。Sp测试服务author福隆苑居士,公众号:【Java分享客栈】since202243011:45ServiceSlf4jpublicclassTestService{privatefinalAsyncServiceasyncSpublicTestService(AsyncServiceasyncService){this。asyncServiceasyncS}模拟并发publicvoidtest(){ConcurrencyTestertesterThreadUtil。concurrencyTest(200,(){测试的逻辑内容try{asyncService。sendMsg();}catch(InterruptedExceptione){log。error(〔TestService〕〔test〕发生异常:,e);}});获取总的执行时间,单位毫秒log。info(总耗时:{},tester。getInterval()ms);}}
  最后,写一个测试接口。packagecom。example。executor。importcom。example。executor。service。TestSimportorg。springframework。http。ResponseEimportorg。springframework。web。bind。annotation。GetMimportorg。springframework。web。bind。annotation。RequestMimportorg。springframework。web。bind。annotation。RestCp测试接口author福隆苑居士,公众号:【Java分享客栈】since202243011:43RestControllerRequestMapping(api)publicclassTestController{privatefinalTestServicetestSpublicTestController(TestServicetestService){this。testServicetestS}GetMapping(test)publicResponseEntityVoidtest(){testService。test();returnResponseEntity。ok()。build();}}
  2、执行顺序
  案例写完了,我们就要开始进行调用线程池的测试了,但在此之前,首先给大家讲明白自定义线程池的配置在运行过程中到底是怎么执行的,是个什么顺序,这个搞明白,后面调整参数就不会困惑了。
  核心线程数(CorePoolSize)(若全部被占用)放入队列(QueueCapacity)(若全部被占用)根据最大线程数(MaxPoolSize)创建新线程(若超过最大线程数)开始执行拒绝策略(RejectedExecutionHandler)
  连看三遍,然后就会了。
  3、核心线程数怎么配
  我们首先把程序跑起来,这里把上面案例的重要线索再理一遍给大家听。
  1)、线程池核心线程数是10,最大线程数是50,队列是200;
  2)、发消息业务是耗时5秒;
  3)、并发工具执行线程数是200。
  可以看到下图,200个线程都执行完了,左边的时间可以观测到,每5秒会执行10个线程,我这边的后台运行可以明显发现很慢才全部执行完200个线程。
  由此可见,核心线程数先执行10个,剩下190个放到了队列,而我们的队列大小是200足够,所以最大线程数没起作用。
  思考:怎么提高200个线程的执行效率?答案已经很明显了,因为我们的业务属于耗时业务花费了5秒,核心线程数配置少了就会导致全部200个线程数执行完会很慢,那么我们只需要增大核心线程数即可。
  我们将核心线程数调到100Bean(namemyExecutor)publicExecutorgetNetHospitalMsgAsyncExecutor(){log。info(CreatingmyExecutorAsyncTaskExecutor);ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(100);executor。setMaxPoolSize(50);executor。setQueueCapacity(200);executor。setThreadNamePrefix(myexecutor);拒绝策略:直接拒绝抛出异常executor。setRejectedExecutionHandler(newThreadPoolExecutor。AbortPolicy());拒绝策略:调用者线程执行executor。setRejectedExecutionHandler(newThreadPoolExecutor。CallerRunsPolicy());}
  看效果:咦?报错了?
  为什么,看源码就知道了。
  原来,线程池初始化时,内部有做判断,最大线程数若小于核心线程数就会抛出这个异常,所以我们设置时要特别注意,至少核心线程数要大于等于最大线程数。
  我们修改下配置:核心线程数和最大线程数都设置为100。ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(100);executor。setMaxPoolSize(100);executor。setQueueCapacity(200);executor。setThreadNamePrefix(myexecutor);
  看效果:后台运行过程中可以发现,运行速度非常快,至少和之前相比提升了10倍,200个线程一会儿就跑完了。
  原因:我们设定的是耗时业务5秒,核心线程数只有10,那么放入队列等待的线程都会分批执行该耗时业务,每批次次5秒就会很慢,当我们把核心线程数调大后,相当于只执行了一两个批次就完成了这5秒业务,速度自然成倍提升。
  这里我们就可以得出第一个结论:
  如果你的业务是耗时业务,线程池配置中的核心线程数就要调大。
  思考一下:
  什么样的业务适合配置较小的核心线程数和较大的队列?
  4、最大线程数怎么配
  接下来,我们来看看最大线程数是怎么回事,这个就有意思了,网上一大堆资料都是错的。
  还是之前的案例,为了更清晰,我们调整一下配置参数:核心线程数4个,最大线程数8个,队列就1个。ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(4);executor。setMaxPoolSize(8);executor。setQueueCapacity(1);executor。setThreadNamePrefix(myexecutor);
  然后我们把并发测试的数量改为10个。ConcurrencyTestertesterThreadUtil。concurrencyTest(10,(){测试的逻辑内容try{asyncService。sendMsg();}catch(InterruptedExceptione){log。error(〔TestService〕〔test〕发生异常:,e);}});
  启动,测试:
  惊喜发现,咦?10个并发数,怎么只有9个执行了,还有1个跑哪儿去啦?
  我们把最大线程数改为7个再试试ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(4);executor。setMaxPoolSize(7);executor。setQueueCapacity(1);executor。setThreadNamePrefix(myexecutor);
  再看看,发现竟然只执行了8个,这下好了,竟然有2个都不翼而飞了
  为什么呢,具体演示效果我会在下面的拒绝策略那里一起演示出来,这里我先直接告诉大家结论:
  最大线程数究竟在线程池中是什么意思,没错,就是字面意思。当核心线程数满了,队列也满了,剩下的线程走最大线程数创建的新线程执行任务,这个流程一开始给大家梳理过。
  但是听好了,因为是最大线程数,所以执行线程怎么样都不会超过这个数字,超过就被拒绝策略拒绝了。
  现在我们再根据本节刚开始的配置参数来梳理一遍,10个并发数,4个占用了核心线程数,1个进入队列,最大线程数配置是8,在当前这2秒的业务时间内,活动线程一共是:
  核心线程数(4)新创建线程数(?)最大线程数(8)
  可见,因为最大线程数配置的是8,所以核心线程数和队列都打满之后,新创建的线程数只能是844个,因此最终执行的就是:
  核心线程数(4)新创建的线程数(4)队列中的线程(1)9
  一点问题都没有,剩下的一个超出最大线程数8所以被拒绝策略拒绝了。
  最后,一张图给你整的明明白白,注意看左边的时间,就知道最后那个是队列里面2秒后执行的线程。
  这里,我们也可以得出第二个结论:
  最大线程数就是字面意思,当前活动线程不能超过这个限制,超过了就会被拒绝策略给拒绝掉。
  5、队列大小怎么配
  前面两个理解了,队列大小其实一个简单的测试就能明白。
  我们修改下之前的线程池配置:
  核心线程数50,最大线程数50,队列100,业务耗时时间改为1秒方便测试。ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(50);executor。setMaxPoolSize(50);executor。setQueueCapacity(100);executor。setThreadNamePrefix(myexecutor);
  并发数设为200ConcurrencyTestertesterThreadUtil。concurrencyTest(200,(){测试的逻辑内容try{asyncService。sendMsg();}catch(InterruptedExceptione){log。error(〔TestService〕〔test〕发生异常:,e);}});
  测试下效果:可以看到,200个并发数,最终只执行了150个,具体算法上一节最大线程数已经讲过不再赘述了。
  这里我们主要明确一点,就是当前线程数超过队列大小后,会走最大线程数去计算后创建新线程来执行业务,那么我们不妨想一下,是不是把队列设置大一点就可以了,这样就不会再走最大线程数。
  我们把队列大小从100调成500看看ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(50);executor。setMaxPoolSize(50);executor。setQueueCapacity(500);executor。setThreadNamePrefix(myexecutor);
  测试效果:可以看到,200个都执行完了,说明我们的设想是正确的。
  这里可以得出第三个结论:
  队列大小设置合理,就不需要走最大线程数造成额外开销,所以配置线程池的最佳方式是核心线程数搭配队列大小。
  6、拒绝策略怎么配
  前面最大线程数如何配置的小节中,经过测试可以发现,超过最大线程数后一部分线程直接被拒绝了,因为我们一开始有配置拒绝策略,这个策略是线程池默认策略,表示直接拒绝。拒绝策略:直接拒绝抛出异常executor。setRejectedExecutionHandler(newThreadPoolExecutor。AbortPolicy());
  那么我们怎么知道这些线程确实是被拒绝了呢,这里我们恢复最大线程数小节中的参数配置。
  然后,把默认策略改为另一个策略:CallerRunsPolicy,表示拒绝后由调用者线程继续执行。ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(4);executor。setMaxPoolSize(7);executor。setQueueCapacity(1);executor。setThreadNamePrefix(myexecutor);拒绝策略:调用者线程执行executor。setRejectedExecutionHandler(newThreadPoolExecutor。CallerRunsPolicy());
  并发数改为10个ConcurrencyTestertesterThreadUtil。concurrencyTest(10,(){测试的逻辑内容try{asyncService。sendMsg();}catch(InterruptedExceptione){log。error(〔TestService〕〔test〕发生异常:,e);}});
  测试效果:
  可以看到10个并发数都执行完了,而最大线程数小节中我们测试时是有2个线程被默认策略拒绝掉的,因为现在策略改成了由调用者线程继续执行任务,所以那2个虽然被拒绝了但还是由调用者线程执行完了。
  可以看到图中红线的两个线程,名称和自定义线程的名称是有明显区别的,这就是调用者线程去执行了。
  那么,这种策略这么人性化,一定是好的吗?
  NO!这种策略反而不可控,如果是互联网项目,在线上很容易出问题,道理很简单。
  线程池占用的不是主线程,是一种异步操作来执行任务,这种策略实际上是把拒绝的线程重新交给了主线程去执行,等于把异步改为了同步,你试想一下,在高峰流量阶段,如果大量异步线程因为这个策略走了主线程是什么后果,很可能导致你主线程的程序崩溃,继而形成服务雪崩。
  展示一下线程池提供的4种策略:
  1)、AbortPolicy:默认策略,直接拒绝并会抛出一个RejectedExecutionException异常;
  2)、CallerRunsPolicy:调用者线程继续执行任务,一种简单的反馈机制策略;
  3)、DiscardPolicy:直接抛弃任务,没有任何通知及反馈;
  4)、DiscardOldestPolicy:抛弃一个老任务,通常是存活时间最长的那个。
  不少人认为CallerRunsPolicy策略是最完善的,但我个人的观点,实际上生产环境中风险最低的还是默认策略,我们线上的项目倾向于优先保证安全。
  讲到这里,结合案例基本上大家能明白这几个线程池参数的含义,那么还记得前面我发出的一个思考题吗,不记得了,因为大家都是鱼的记忆,思考题是:
  什么样的业务适合配置较小的核心线程数和较大的队列?
  答案:低耗时、高并发的场景非常适合,因为低耗时都属于毫秒级业务,这种业务走CPU和内存会更合适,高并发时需要队列缓冲,同时因为低耗时又不会在队列中长时间等待,核心线程数较大会一次性增加CPU过大的开销,所以配置较小的核心线程数和较大的队列就很适合这种场景。
  题外话,用过云产品的就知道,你选购云服务器时,总会让你选什么CPU密集型和IO密集型之类的款型,如果你对线程池比较了解,就能知道什么意思,不同的项目需要搭配的服务器款型实际上是有考量的,上面的场景就显然要选CPU密集型的服务器,而本章前面的案例场景是高耗时的就适合IO密集型的服务器。
  三、总结
  这里面除了针对本章总结,还额外增加了几点,来源于我的工作经验。
  1)、如果你的业务是耗时业务,线程池配置中的核心线程数就要调大,队列就要适当调小;
  2)、如果你的业务是低耗时业务(毫秒级),同时流量较大,线程池配置中的核心线程数就要调小,队列就要适当调大;
  3)、最大线程数就是字面意思,当前活动线程不能超过这个限制,超过了就会被拒绝策略给拒绝掉;
  4)、队列大小设置合理,就不需要走最大线程数造成额外开销,所以配置线程池的最佳方式是核心线程数搭配队列大小;
  5)、线程池拒绝策略尽量以默认为主,降低生产环境风险,非必要不改变;
  6)、同一个服务器中部署的项目或微服务,全部加起来的线程池数量最好不要超过5个,否则生死有命富贵在天;
  7)、线程池不要乱用,分清楚业务场景,尽量在可以延迟且不是特别重要的场景下使用,比如我这里的发消息,或者发订阅通知,或者做某个场景的日志记录等等,千万别在核心业务中轻易使用线程池;
  8)、线程池不要混用,特定业务记得隔离,也就是自定义各自的线程池,不同的名称不同的参数,你可以试想一下你随手写了一个线程池,配置了自己那块业务合适的参数,结果被另一个同事拿去在并发量大的业务中使用了,到时候只能有难同当了;
  9)、线程池配置不是请客吃饭,哪怕你很熟悉,请在上线前依然做一下压测,这是本人惨痛的教训;
  10)、请一定要明确线程池的应用场景,切勿和高并发处理方案混淆在一起,这俩业务上针对的方向完全不同。
  文章来自https:www。cnblogs。comfulongyuanjuship16214051。html
投诉 评论 转载

蒙内铁路助力肯尼亚经济社会发展中国标准闪耀东非央视网消息:近日,肯尼亚国家统计局发布数据显示,由中国企业承建的蒙内铁路去年营收达153亿肯尼亚先令(约合人民币7。88亿元),客运量和货运量均稳步增长,为肯尼亚经济社会发展持……SpringBoot参数搜一堆资料还是不会配,我花一天测试换案例1、编写案例自定义一个线程池,并加上初始配置。核心线程数10,最大线程数50,队列大小200,自定义线程池名称前缀为myexecutor,以及线程池拒绝策略为A……电视机迎来MiniLED时代,你准备好了吗?电视机作为视频和广播的通信信息外,还给人们带来新闻的传输路径,如今时代在不断更新,创造更高科技的产品时代,电视机也迎来MiniLED时代。以更快,广,稳制造提升电视显示屏……ChatGpt建议当下快做十个闷声发大财的生意利润高,但做的ChatGPT以下是十个利润高、但做的人比较少的闷声发大财生意:氧化铝制品生产:氧化铝制品广泛应用于陶瓷、玻璃、建筑等领域,而且利润高,但很少有人涉足此行业。锂电池回收:……越南旅欧第一人阮公凤火线归队!中国球迷他给武磊提鞋都够呛带着两连败的开局,中国男足即将在世预赛亚洲区12强赛迎来下一个对手越南队。面对同样开局连败的不利形势,这支特点鲜明的东南亚球队当然也渴望在国足身上首获积分,而队内头号球星,也是……文明之美看东方这里最早叫中国中华文明起源的陶寺模式来源:山西云媒体没有哪一个遗址能像陶寺遗址这样,全面拥有文明起源形成的要素和标志。陶寺遗址作为中华文明探源工程中三大重点遗址之一,是研究中国历史和古代文化,感知中华民族精……欧冠巴萨幸运拿平局,丧失出线主动权,成欧联杯夺冠热门?头条创作挑战赛巴萨欧冠小组赛第4轮,主场艰难逼平国米,没有让对手提前2轮出线,但是自己的出线希望也仅剩下理论上还有机会。夏天投入了那么大的巴萨,在欧冠小组赛有如此表现,绝……马云去哪了?马云去哪了?最近成为了一个热门话题。当然他去哪是他的自由,只是他去的地方有点令人意想不到,这种选择或许是为了保持某种联系。不得不说,马云的确是改变影响中国的人物之一……最新!小微企业个体工商户所得税优惠政策明确关于小微企业和个体工商户所得税优惠政策的公告财政部税务总局公告2023年第6号为支持小微企业和个体工商户发展,现将有关税收政策公告如下:一、对小型微利企业年应……国足战越南首发大猜想中锋:张玉宁左前卫:洛国富前腰:戴伟浚右前卫:武磊阿兰中前卫:吴曦后腰:徐新左边后卫:王燊超中后卫组合:朱辰杰蒋光太右边后卫:邓……阔腿裤穿法升级了,借鉴三木博主的这5种高级搭配,真美历经了寒冷的冬季,终于迎来了明媚的阳光和上升的温度。虽然寒冷慢慢褪去,也是春光明媚,但在晨间与傍晚,也仍旧能够感受到丝丝的凉意。在这换季之时,在将厚重的冬装都收起来之时,……休赛季最失意球星,7人签下顶薪合同,艾顿却无人报价NBA的休赛季同样是紧张刺激的,球星们会抓住假期的时间提升自己,而各大球队也会在自由市场上,寻求交易和补强。自由市场的大幕拉开之后,联盟就有多位球员捞到了大合同。今年堪称是大合……
NVIDIA451。48版显卡驱动发布唯一完整支持DX12终景区门票分时段预约。分时预约。实名制预约系统搭配金手柄24K黄金限量版索尼PS5公布预计今年推出微软更多设备将自动升级至Windows10五月更新韩红自称当年是大学校花,大家以为是玩笑,看到18岁照片被惊艳暗香浮动!中山公园的蜡梅花开了Chrome浏览器全新界面上线帅爆!好评!Chrome浏览器在Win10上总算满血了N年老用户弃用Chrome浏览器后舒服了失眠可能是肺出现了问题Chrome浏览器更强大了全球份额已达711809版用户吐槽自己被强迫升级至Win105月更新如何把握同事间的“静”与“远”公司劳动合同刘嘉玲为梁朝伟庆生刘嘉玲为何不生孩子原因童鞋会甲醛超标吗韩国实拍第十代索纳塔!由内而外全面提升设计遭吐槽传奇世界法师武器怎么选?法师装备推荐,你都知道有哪些小学体育教学具体工作计划学习是有方法和技巧的,关于有效学习,我有。。。侵犯商标专用权怎么确定管辖孩子在校不懂礼貌怎么办孩子在校不懂礼貌如何教导九牛一毛成语故事今日嘉兴青菜价格(今日菜价)

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找美丽时装彩妆资讯历史明星乐活安卓数码常识驾车健康苹果问答网络发型电视车载室内电影游戏科学音乐整形