范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

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

  案例1、编写案例
  自定义一个线程池,并加上初始配置。
  核心线程数10,最大线程数50,队列大小200,自定义线程池名称前缀为my-executor-,以及线程池拒绝策略为AbortPolicy,也是默认策略,表示直接放弃任务。 package com.example.executor.config;  import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor;  @Configuration @EnableAsync @EnableScheduling @Slf4j public class AsyncConfiguration {     /**     * 自定义线程池     */    @Bean(name = "myExecutor")    public Executor getNetHospitalMsgAsyncExecutor() {       log.info("Creating myExecutor Async Task Executor");       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();       executor.setCorePoolSize(10);       executor.setMaxPoolSize(50);       executor.setQueueCapacity(200);       executor.setThreadNamePrefix("my-executor-");       // 拒绝策略:直接拒绝抛出异常       executor.setRejectedExecutionHandler(             new ThreadPoolExecutor.AbortPolicy());       return executor;    } }
  接下来,我们写一个异步服务,直接使用这个自定义线程池,并且模拟一个耗时5秒的发消息业务。 package com.example.executor.service;  import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit;  /**  * 

* 异步服务 * * * @author 福隆苑居士,公众号:【Java分享客栈】 * @since 2022/4/30 11:41 */ @Service @Slf4j public class AsyncService { /** * 模拟耗时的发消息业务 */ @Async("myExecutor") public void sendMsg() throws InterruptedException { log.info("[AsyncService][sendMsg]>>>> 发消息...."); TimeUnit.SECONDS.sleep(5); } }   然后,我们写一个TestService,使用Hutools自带的并发工具来调用上面的发消息服务,并发数设置为200,也就是同时开启200个线程来执行业务。 package com.example.executor.service; import cn.hutool.core.thread.ConcurrencyTester; import cn.hutool.core.thread.ThreadUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** *

* 测试服务 * * * @author 福隆苑居士,公众号:【Java分享客栈】 * @since 2022/4/30 11:45 */ @Service @Slf4j public class TestService { private final AsyncService asyncService; public TestService(AsyncService asyncService) { this.asyncService = asyncService; } /** * 模拟并发 */ public void test() { ConcurrencyTester tester = ThreadUtil.concurrencyTest(200, () -> { // 测试的逻辑内容 try { asyncService.sendMsg(); } catch (InterruptedException e) { log.error("[TestService][test]>>>> 发生异常: ", e); } }); // 获取总的执行时间,单位毫秒 log.info("总耗时:{}", tester.getInterval() + " ms"); } }   最后,写一个测试接口。 package com.example.executor.controller; import com.example.executor.service.TestService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** *

* 测试接口 * * * @author 福隆苑居士,公众号:【Java分享客栈】 * @since 2022/4/30 11:43 */ @RestController @RequestMapping("/api") public class TestController { private final TestService testService; public TestController(TestService testService) { this.testService = testService; } @GetMapping("/test") public ResponseEntity test() { testService.test(); return ResponseEntity.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个线程数执行完会很慢,那么我们只需要增大核心线程数即可。   我们将核心线程数调到100 @Bean(name = "myExecutor") public Executor getNetHospitalMsgAsyncExecutor() { log.info("Creating myExecutor Async Task Executor"); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(100); executor.setMaxPoolSize(50); executor.setQueueCapacity(200); executor.setThreadNamePrefix("my-executor-"); // 拒绝策略:直接拒绝抛出异常 executor.setRejectedExecutionHandler( new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略:调用者线程执行 // executor.setRejectedExecutionHandler( // new ThreadPoolExecutor.CallerRunsPolicy()); return executor; }   看效果:咦?报错了?   为什么,看源码就知道了。   原来,线程池初始化时,内部有做判断,最大线程数若小于核心线程数就会抛出这个异常,所以我们设置时要特别注意,至少核心线程数要大于等于最大线程数。   我们修改下配置:核心线程数和最大线程数都设置为100. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(100); executor.setMaxPoolSize(100); executor.setQueueCapacity(200); executor.setThreadNamePrefix("my-executor-");   看效果:后台运行过程中可以发现,运行速度非常快,至少和之前相比提升了10倍,200个线程一会儿就跑完了。   原因:我们设定的是耗时业务5秒,核心线程数只有10,那么放入队列等待的线程都会分批执行该耗时业务,每批次次5秒就会很慢,当我们把核心线程数调大后,相当于只执行了一两个批次就完成了这5秒业务,速度自然成倍提升。   这里我们就可以得出第一个结论:   如果你的业务是耗时业务,线程池配置中的核心线程数就要调大。   思考一下:   什么样的业务适合配置较小的核心线程数和较大的队列?   4、最大线程数怎么配   接下来,我们来看看最大线程数是怎么回事,这个就有意思了,网上一大堆资料都是错的。   还是之前的案例,为了更清晰,我们调整一下配置参数:核心线程数4个,最大线程数8个,队列就1个。 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(1); executor.setThreadNamePrefix("my-executor-");   然后我们把并发测试的数量改为10个。 ConcurrencyTester tester = ThreadUtil.concurrencyTest(10, () -> { // 测试的逻辑内容 try { asyncService.sendMsg(); } catch (InterruptedException e) { log.error("[TestService][test]>>>> 发生异常: ", e); } });   启动,测试:   惊喜发现,咦?10个并发数,怎么只有9个执行了,还有1个跑哪儿去啦?   我们把最大线程数改为7个再试试 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(7); executor.setQueueCapacity(1); executor.setThreadNamePrefix("my-executor-");   再看看,发现竟然只执行了8个,这下好了,竟然有2个都不翼而飞了……   为什么呢,具体演示效果我会在下面的拒绝策略那里一起演示出来,这里我先直接告诉大家结论:     最大线程数究竟在线程池中是什么意思,没错,就是字面意思。当核心线程数满了,队列也满了,剩下的线程走最大线程数创建的新线程执行任务,这个流程一开始给大家梳理过。     但是听好了,因为是最大线程数,所以执行线程怎么样都不会超过这个数字,超过就被拒绝策略拒绝了。     现在我们再根据本节刚开始的配置参数来梳理一遍,10个并发数,4个占用了核心线程数,1个进入队列,最大线程数配置是8,在当前这2秒的业务时间内,活动线程一共是:      核心线程数(4) + 新创建线程数(?) = 最大线程数(8)     可见,因为最大线程数配置的是8,所以核心线程数和队列都打满之后,新创建的线程数只能是8-4=4个,因此最终执行的就是:      核心线程数(4) + 新创建的线程数(4) + 队列中的线程(1) = 9     一点问题都没有,剩下的一个超出最大线程数8所以被拒绝策略拒绝了。   最后,一张图给你整的明明白白,注意看左边的时间,就知道最后那个是队列里面2秒后执行的线程。   这里,我们也可以得出第二个结论:   最大线程数就是字面意思,当前活动线程不能超过这个限制,超过了就会被拒绝策略给拒绝掉。   5、队列大小怎么配   前面两个理解了,队列大小其实一个简单的测试就能明白。   我们修改下之前的线程池配置:   核心线程数50,最大线程数50,队列100,业务耗时时间改为1秒方便测试. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(50); executor.setMaxPoolSize(50); executor.setQueueCapacity(100); executor.setThreadNamePrefix("my-executor-");   并发数设为200 ConcurrencyTester tester = ThreadUtil.concurrencyTest(200, () -> { // 测试的逻辑内容 try { asyncService.sendMsg(); } catch (InterruptedException e) { log.error("[TestService][test]>>>> 发生异常: ", e); } });   测试下效果:可以看到,200个并发数,最终只执行了150个,具体算法上一节最大线程数已经讲过不再赘述了。   这里我们主要明确一点,就是当前线程数超过队列大小后,会走最大线程数去计算后创建新线程来执行业务,那么我们不妨想一下,是不是把队列设置大一点就可以了,这样就不会再走最大线程数。   我们把队列大小从100调成500看看 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(50); executor.setMaxPoolSize(50); executor.setQueueCapacity(500); executor.setThreadNamePrefix("my-executor-");   测试效果:可以看到,200个都执行完了,说明我们的设想是正确的。   这里可以得出第三个结论:   队列大小设置合理,就不需要走最大线程数造成额外开销,所以配置线程池的最佳方式是核心线程数搭配队列大小。   6、拒绝策略怎么配   前面最大线程数如何配置的小节中,经过测试可以发现,超过最大线程数后一部分线程直接被拒绝了,因为我们一开始有配置拒绝策略,这个策略是线程池默认策略,表示直接拒绝。 // 拒绝策略:直接拒绝抛出异常 executor.setRejectedExecutionHandler( new ThreadPoolExecutor.AbortPolicy());   那么我们怎么知道这些线程确实是被拒绝了呢,这里我们恢复最大线程数小节中的参数配置。   然后,把默认策略改为另一个策略:CallerRunsPolicy,表示拒绝后由调用者线程继续执行。 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(7); executor.setQueueCapacity(1); executor.setThreadNamePrefix("my-executor-"); // 拒绝策略:调用者线程执行 executor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy()); return executor;   并发数改为10个 ConcurrencyTester tester = ThreadUtil.concurrencyTest(10, () -> { // 测试的逻辑内容 try { asyncService.sendMsg(); } catch (InterruptedException e) { 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.com/fulongyuanjushi/p/16214051.html


OPPO公关黄宏涛,发引战言论诋毁鸿蒙操作系统,你对此事怎么看?近日华为官宣,在6月2日举办鸿蒙操作系统发布会时,OPPO的公关经理黄宏涛第一个站出来,说不会使用华为的鸿蒙系统,并用粗暴的语气发表引战言论,用词极其恶毒,简直让人不忍直视!OPP中国供应全球80电动车电池!美国坐不住了拟斥1。1万亿追赶中国垄断全球80的电池供应,昔日电池巨头美国惊慌失措,斥资1。1万亿穷追猛赶。近年来,作为中国各行业的竞争敌手,美国开始越发重视我们各行业的发展,上至建筑工程技术,下到小小的电池,戴威,败光百亿成老赖,被1600万人追债,他的故事有多惨?1817年,第一辆自行车在法国巴黎诞生,从此,人们的出行方式就发生了巨变。虽然现在又有了汽车电瓶车等私人交通工具,但相比之下,最环保的自行车依然是许多人出行时的不二之选。自行车最大华为Mate50Pro售价曝光,或将7月份发布,王者归来声明原创不易,禁止搬运,违者必究!说起华为的手机业务,还是有不少人表示意难平。有了自研的麒麟芯片,并且在业界口碑还非常好,却因为代工厂商问题,而无法实现量产,从而出现缺芯。在5G技想买华为手机,必选华为在美丽国一次又一次的打压下,展现出来了不一样的生机与活力,是在用一个公司的力量,来对抗美国这一超级大国,但也不完全对,因为在华为背后,还有一个强大的祖国,还有祖国的千千万人民,华为MateXs2将升级120Hz高刷屏依旧外折叠方案售价约1。6万元经过多日爆料,华为官方日前宣布,将在4月28日举行华为折叠屏旗舰及全场景新品发布会,届时全新的华为MateXs2折叠屏旗舰将正式与大家见面。而随着发布时间日益临近,外界关于该机的爆华为为什么把手机品牌荣耀独立出来?转眼间,荣耀已经5岁了。5年前,我们勇敢做自己,5年后,我们拥抱潮流,主张活出,我的荣耀。带你看看这其中的故事。移动互联网时代,顺应时势,自我革命和进步。华为内部对终端业务何去何从00852开头的电话天天打,怎么办?拉入黑名单就行了00852是香港区号,你先听听,然后挂断。直接听可以在运营商的app上开通一个免费高频电话拦截服务。中国移动的就有,其他运营商的可以联系一下客服。以下教程仅供参考。什么叫做RIC助听器?您好!什么叫做RIC助听器?RIC指的是助听器中的受话器外置的一种。这种助听器属于耳背式的一种,但是它比常规耳背式更小巧,不易被察觉。功能方面也比定制机更多,按键齐全。从性能上来讲小米Civi1s与小米Civi有什么区别?小米Civi1S相比小米Civi主要有3个升级,处理器换成了骁龙778G芯片,自拍部分加入了前置人眼追焦功能与美颜技术再次升级,还带来了全新的奇迹阳光配色。其他方面保持不比,依旧是网购家电靠谱吗,为什么比实体店便宜?线上和线下产品有区别吗?网络专供,实体专供,你说有没有区别,使用的材料都不一样,你说有没有区别,明眼看差不多,其实用的材料有很大差别,厚度,光泽度,颜色都有差别。咱们日常生活中都离不开家电,但是大家对于购
曲面屏明明是高端手机标配,可为什么现在厂家都开始放弃曲面屏了不知道大家有没有发现,这两年我们去手机商城,凡是高端旗舰机都会采用曲面屏,而直屏大多都是中低端机子,形成了一种曲面屏手机成了高端手机的标配一样,在这里不得不说一句,当年被三星玩剩下价值32万元且上过太空!祖宗级AppleWatch将被拍卖中关村在线消息据Appleinsider报道,一款1988年从未佩戴过的WristMac智能手表,仍保留原包装,预计拍卖价将在25,000美元(合人民币约16万元)至50,000美工信部发布第二批5G工业互联网典型应用场景新华社北京11月22日电(记者张辛欣)记者22日从工信部获悉,工信部发布第二批5G工业互联网典型应用场景和重点行业实践。厂区智能理货全域物流监测这些正作为典型应用场景,在越来越多的在IDC关于2022年中国ICT市场预测中看数据中心的机遇IDC2022年中国ICT市场十大预测具体内容如下预测一行业深度数字化加速,数字化产品与服务机会可期十四五规划明确提出促进数字技术与实体经济深度融合,加快推进产业数字化转型,加快数日本超级计算机名将,算力达到44。2亿亿次,与中国团队存差别不久前,全球超级计算机TOP500强公布了最新的榜单,日本名将富岳超级计算机再次出征,又一次登上了榜首,成为了世界上运行最快的计算机。曾经中国超级计算机,也以最快的方式,连续多次位百度网盘将推出青春版,联发科天玑9000正式发布1百度网盘将推出青春版不限下载速度,只有10GB免费存储空间(IT之家)近日,百度网盘腾讯微云天翼云盘和彩云阿里云盘迅雷云盘360安全云盘和网易网盘8家网盘企业承诺年内将推出无差别长光辰芯国产8K图像传感器通过验收实现国内自生产CNMO新闻近日由国内企业长光辰芯联合浙江华睿科技股份有限公司深圳市大疆创新科技有限公司及深圳市大疆百旺科技有限公司等数家企业联合研发的8K超高清图像传感器芯片正式通过验收,该芯片11。22收盘场内ETF基金大全涨幅排名新能源芯片大涨多点开花特别注意(一)单纯的基金定投不需要择时的,做好几年的计划,精选几个标的,每天定投10元即可。可以参考我的(顶置文章)定投计划基金定投计划消费医药科技新能源指数均衡(二)场内ETF买深圳知名电商公司墨灿倒闭,干倒实体的电商为何也如此艰难?任何产品都有它一个本来的价值(成本利润),本来的质量体系。真正的电商运营应该是保证质量的前提下,赚取中间商差价而已。结果是全国电商大乱斗,疯狂工厂压价。而工厂只能在成本上下手,部分为什么乘客车主出租车司机,都对滴滴颇有微词?乘客因为平台为了订单没底线的跪舔乘客,又是优惠卷又是一口价,打滴滴比坐公交还便宜,长期以往惯坏了乘客好多臭毛病,乘客可以随便投诉,几块钱就想享受专车服务。车主出人出车出油承担一切安618手机格局大变,iQOO成销量黑马直逼第一卖爆了,是今年618大众对iQOO的首要印象。618期间,iQOO连获京东安卓手机品牌销量销售额TOP2天猫安卓手机品牌销售额TOP2和苏宁安卓手机品牌销量TOP2,战绩强悍,势头