SpringBoot 自定义线程池

文章目录

          • 一、自定义线程池
            • 1. yml配置
            • 2. 线程池配置属性类
            • 3. 开启异步线程支持
            • 4. 创建自定义线程池配置类
            • 5. service逻辑层
            • 6. controller控制层
            • 7. 效果图
          • 二、配置默认线程池
            • 2.1. yml
            • 2.2.线程池配置属性类
            • 2.3. 开启异步线程支持
            • 2.4. 装配线程池
            • 2.5. service逻辑层
            • 2.6. controller控制层
            • 2.7. 效果图

自定义线程池有2种方法:
第一种:是自定义线程池,使用时指定线程池名称,执行异步任务。
第二种:重写spring默认线程池,然后使用自己重写后的线程池,执行异步任务。

一、自定义线程池
1. yml配置
# 线程池配置参数
task:pool:corePoolSize: 10 # 设置核心线程数maxPoolSize: 20  # 设置最大线程数keepAliveTime: 300 # 设置空闲线程存活时间(秒)queueCapacity: 100 # 设置队列容量threadNamePrefix: "gblfy-signpolicy-asynnotify-" # 设置线程名称前缀awaitTerminationSeconds: 60 #  设置线程池等待终止时间(秒)
spring:main:allow-bean-definition-overriding: true
2. 线程池配置属性类
package com.gblfy.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** 线程配置属性类** @Author gblfy* @Date 2022-04-05 17:20**/
@Data
@ConfigurationProperties(prefix = "task.pool")
public class TaskThreadPoolConfig {private int corePoolSize;private int maxPoolSize;private int keepAliveSeconds;private int queueCapacity;private int awaitTerminationSeconds;private String threadNamePrefix;
}
3. 开启异步线程支持

在启动类上/开启异步线程支持+开启配置属性支持

package com.gblfy;import com.gblfy.config.TaskThreadPoolConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableAsync;@EnableAsync//开启异步线程支持
@EnableConfigurationProperties({TaskThreadPoolConfig.class})//开启配置属性支持
@SpringBootApplication
public class AsyncThreadApplication {public static void main(String[] args) {SpringApplication.run(AsyncThreadApplication.class, args);}}
4. 创建自定义线程池配置类
package com.gblfy.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;/*** 创建自定义线程池配置类** @Author gblfy* @Date 2022-04-05 17:26**/
@Configuration
public class AsyncScheduledTaskConfig {@Autowiredprivate TaskThreadPoolConfig config;/*** 1.这种形式的线程池配置是需要在使用的方法上面添加@Async("customAsyncThreadPool")注解的* 2。如果在使用的方法上不添加该注解,那么spring就会使用默认的线程池* 3.所以如果添加@Async注解但是不指定使用的线程池,又想自己自定义线程池,那么就可以重写spring默认的线程池* 4.所以第二个方法就是重写spring默认的线程池** @return*/@Bean("customAsyncThreadPool")public Executor customAsyncThreadPool() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//最大线程数executor.setMaxPoolSize(config.getMaxPoolSize());//核心线程数executor.setCorePoolSize(config.getCorePoolSize());//任务队列的大小executor.setQueueCapacity(config.getQueueCapacity());//线程池名的前缀executor.setThreadNamePrefix(config.getThreadNamePrefix());//允许线程的空闲时间30秒executor.setKeepAliveSeconds(config.getKeepAliveSeconds());//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Beanexecutor.setWaitForTasksToCompleteOnShutdown(true);//设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());/*** 拒绝处理策略* CallerRunsPolicy():交由调用方线程运行,比如 main 线程。* AbortPolicy():直接抛出异常。* DiscardPolicy():直接丢弃。* DiscardOldestPolicy():丢弃队列中最老的任务。*//*** 特殊说明:* 1. 这里演示环境,拒绝策略咱们采用抛出异常* 2.真实业务场景会把缓存队列的大小会设置大一些,* 如果,提交的任务数量超过最大线程数量或将任务环缓存到本地、redis、mysql中,保证消息不丢失* 3.如果项目比较大的话,异步通知种类很多的话,建议采用MQ做异步通知方案*/executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//线程初始化executor.initialize();return executor;}
}
5. service逻辑层
package com.gblfy.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;/*** 自定义线程池测试1** @Author gblfy* @Date 2022-04-05 17:55**/
@Service
public class ThreadPoolService {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService.class);@Async("customAsyncThreadPool")//指定使用哪个线程池配置,不然会使用spring默认的线程池public void executeAsync() {System.out.println("executeAsync");LOGGER.info("当前运行线程名称:{}", Thread.currentThread().getName());}
}
package com.gblfy.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;/*** 自定义线程池测试2** @Author gblfy* @Date 2022-04-05 17:55**/
@Service
public class ThreadPoolService2 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService2.class);@Async("customAsyncThreadPool")//指定使用哪个线程池配置,不然会使用spring默认的线程池public void executeAsync() {System.out.println("executeAsync2");LOGGER.info("当前运行线程名称:{}", Thread.currentThread().getName());}
}
6. controller控制层
package com.gblfy.controller;import com.gblfy.service.ThreadPoolService;
import com.gblfy.service.ThreadPoolService2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 自定义线程池侧是** @Author gblfy* @Date 2022-04-05 17:54**/
@RestController
public class ThreadPoolController {@Autowiredprivate ThreadPoolService threadPoolService;@Autowiredprivate ThreadPoolService2 threadPoolService2;@GetMapping("/threadPoolTest")public void threadPoolTest() {threadPoolService.executeAsync();threadPoolService2.executeAsync();}
}
7. 效果图

浏览器请求:http://localhost:8080/threadPoolTest
在这里插入图片描述

二、配置默认线程池

第一种线程池配置是需要在使用的方法上面添加@Async(“customAsyncThreadPool”)注解的。
而这种方式是重写spring默认的线程池,使用的方法上面添加@Async注解,不用去声明线程池类

2.1. yml
# 线程池配置参数
task:pool:corePoolSize: 10 # 设置核心线程数maxPoolSize: 20  # 设置最大线程数keepAliveTime: 300 # 设置空闲线程存活时间(秒)queueCapacity: 100 # 设置队列容量threadNamePrefix: "gblfy-signpolicy-asynnotify-" # 设置线程名称前缀awaitTerminationSeconds: 60 #  设置线程池等待终止时间(秒)
spring:main:allow-bean-definition-overriding: true
2.2.线程池配置属性类
package com.gblfy.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** 线程配置属性类** @Author gblfy* @Date 2022-04-05 17:20**/
@Data
@ConfigurationProperties(prefix = "task.pool")
public class TaskThreadPoolConfig {private int corePoolSize;private int maxPoolSize;private int keepAliveSeconds;private int queueCapacity;private int awaitTerminationSeconds;private String threadNamePrefix;
}
2.3. 开启异步线程支持

在启动类上/开启异步线程支持+开启配置属性支持

package com.gblfy;import com.gblfy.config.TaskThreadPoolConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableAsync;@EnableAsync//开启异步线程支持
@EnableConfigurationProperties({TaskThreadPoolConfig.class})//开启配置属性支持
@SpringBootApplication
public class AsyncThreadApplication {public static void main(String[] args) {SpringApplication.run(AsyncThreadApplication.class, args);}}
2.4. 装配线程池
package com.gblfy.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;/*** 原生(Spring)异步线程池装配类* 实现AsyncConfigurer接口,重写getAsyncExecutor和getAsyncUncaughtExceptionHandler方法,* 这样使用默认线程池时就会使用自己重写之后的线程池** @Author gblfy* @Date 2022-04-05 17:26**/
@Configuration
public class NativeAsyncScheduledTaskConfig implements AsyncConfigurer {private static final Logger LOGGER = LoggerFactory.getLogger(NativeAsyncScheduledTaskConfig.class);@Autowiredprivate TaskThreadPoolConfig config;@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//最大线程数executor.setMaxPoolSize(config.getMaxPoolSize());//核心线程数executor.setCorePoolSize(config.getCorePoolSize());//任务队列的大小executor.setQueueCapacity(config.getQueueCapacity());//线程池名的前缀executor.setThreadNamePrefix(config.getThreadNamePrefix());//允许线程的空闲时间30秒executor.setKeepAliveSeconds(config.getKeepAliveSeconds());//设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Beanexecutor.setWaitForTasksToCompleteOnShutdown(true);//设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());/*** 拒绝处理策略* CallerRunsPolicy():交由调用方线程运行,比如 main 线程。* AbortPolicy():直接抛出异常。* DiscardPolicy():直接丢弃。* DiscardOldestPolicy():丢弃队列中最老的任务。*//*** 特殊说明:* 1. 这里演示环境,拒绝策略咱们采用抛出异常* 2.真实业务场景会把缓存队列的大小会设置大一些,* 如果,提交的任务数量超过最大线程数量或将任务环缓存到本地、redis、mysql中,保证消息不丢失* 3.如果项目比较大的话,异步通知种类很多的话,建议采用MQ做异步通知方案*/executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//线程初始化executor.initialize();return executor;}/*** 异步任务重异常处理** @return*/@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {LOGGER.error(ex.getMessage(), ex);LOGGER.error("excetion method:{}", method.getName());};}// @Override// public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {//     return new AsyncUncaughtExceptionHandler() {//         @Override//         public void handleUncaughtException(Throwable ex, Method method, Object... params) {//             LOGGER.error(ex.getMessage(),ex);//             LOGGER.error("excetion method:{}",method.getName());//         }//     };// }
}
2.5. service逻辑层
package com.gblfy.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;/*** 重写Spring默认线程池测试1** @Author gblfy* @Date 2022-04-05 17:55**/
@Service
public class ThreadPoolService3 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService3.class);@Asyncpublic void executeAsync() {System.out.println("executeAsync3");LOGGER.info("当前运行线程名称:{}", Thread.currentThread().getName());}
}
package com.gblfy.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;/*** 重写Spring默认线程池测试2** @Author gblfy* @Date 2022-04-05 17:55**/
@Service
public class ThreadPoolService4 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService4.class);@Asyncpublic void executeAsync() {System.out.println("executeAsync4");LOGGER.info("当前运行线程名称:{}", Thread.currentThread().getName());}
}
2.6. controller控制层
package com.gblfy.controller;import com.gblfy.service.ThreadPoolService3;
import com.gblfy.service.ThreadPoolService4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** 自定义线程池侧是** @Author gblfy* @Date 2022-04-05 17:54**/
@RestController
public class ThreadPoolController2 {@Autowiredprivate ThreadPoolService3 threadPoolService3;@Autowiredprivate ThreadPoolService4 threadPoolService4;@GetMapping("/threadPoolTest2")public void threadPoolTest2() {threadPoolService3.executeAsync();threadPoolService4.executeAsync();}
}
2.7. 效果图

浏览器请求:http://localhost:8080/threadPoolTest2
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/515796.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可用性SLA还不懂?看完这个故事就懂了

大家好,我是小编云BliBli, 这些天 领导问了我一个暴击我灵魂的问题: 什么是SLA?那么多9到底是什么意思? (瓦特??我怎么知道????&#…

如何通过 Serverless 轻松识别验证码?

来源 | Serverless责编 | 晋兆雨头图 | 付费下载于视觉中国前言Serverless 概念自被提出就倍受关注,尤其是近些年来 Serverless 焕发出了前所未有的活力,各领域的工程师都在试图将 Serverless 架构与自身工作相结合,以获取到 Serverless 架构…

怀里橘猫柴犬,掌上代码江湖——对话阿里云MVP郭旭东

云栖号资讯:【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 简介: 跟郭旭东聊过之后,我对程序员的敬佩又多一分。这个92年的开发者,难能可贵地兼备朝气…

防止重复提交 最佳实践

文章目录一、方案评估1. 前端2. 后端方案二、代码实战2.1. 依赖2.2. yml配置2.2. 相关配置类2.3. 实体类2.4. 相关工具类2.5. 操作消息提醒2.6. 过滤器2.2. 拦截器2.7.重复提交测试2.8. 效果图一、方案评估 1. 前端 提交后屏蔽提交按钮 2. 后端方案 实现原理 1.自定义重复提…

java实现 - 树的层序遍历

树: 树实体结构: Data public class Tree {//树的data值private String dataStr;//树的第一个孩子节点private Tree firstChild;//树的下一个孩子节点private Tree nextBrother; }代码实现: public class TreeTraversal {//队列&#xff…

金山云发布全新Serverless产品 云原生基础设施再升级

随着企业数字化转型的深入,云计算正全面步入2.0时代,即为云而生的阶段。以云原生为代表的理念,已经成为进一步释放云计算价值的核心推动力。 1月6日,金山云举行了云原生媒体沟通会,金山云副总裁、合伙人钱一峰在会上正…

如何提升微服务的幸福感

前言 随着微服务的流行,越来越多公司使用了微服务框架,微服务以其的高内聚、低耦合等特性,提供了更好的容错性,也更适应业务的快速迭代,为开发人员带来了很多的便利性。但是随着业务的发展,微服务拆分越来…

nacos未授权访问漏洞【原理扫描】

解决方案 vim /nacos/conf/application.properties添加 #开启认证配置 nacos.core.auth.enabledtrue

求AOE图的 拓扑排序 及关键路径长度(java实现)

文章目录1.AOE图:2.AOE图邻接链表存储结构:3.代码实现3.1.实体及参数初始化3.2.代码实现3.3.输出1.AOE图: 2.AOE图邻接链表存储结构: 3.代码实现 3.1.实体及参数初始化 //邻接表的链表节点 Data public class LinkedNode {//邻接…

陈旸:清华博士的模型信仰

云栖号资讯:【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 简介: 陈旸是典型的天才学霸。10岁开始编程,亚洲奖、国奖拿到手软;创业做新媒体&#xff…

创业公司用 Serverless,到底香不香?

来源 | Serverless责编 | 晋兆雨头图 | 付费下载于视觉中国在过去的 5 年里,使用云厂商处理应用后台的流行程度大幅飙升。其一,初创企业主采用 Serverless 方式,以节省基础设施成本,并随用随付。随着公司规模的扩大,依…

Too many files with unapproved license: 2 See RAT report

解决方案 mvn -Prelease-nacos -Dmaven.test.skiptrue -Dpmd.skiptrue -Dcheckstyle.skiptrue -Drat.numUnapprovedLicenses100 clean install -U或者 mvn -Prelease-nacos -Dmaven.test.skiptrue -Drat.numUnapprovedLicenses100 clean install -U

高速公路智能化转型,阿里云高速云控平台如何赋能?

目前我国高速公路通车里程位居世界第一,但"高速路不高速"却时常发生,每逢出行高峰期,高速公路的拥堵状况会愈发严重。我国高速出行主要面临的痛点是安全和拥堵,主要是由路网利用不均衡、数据价值挖掘不够、协同管理平台…

2021 云原生开门红,金山云发布全新云原生全景图

据云原生计算基金会(CNCF)数据显示,当前企业已经在广泛使用云原生技术,容器应用已成常态, 2019 年 84% 的公司在生产中使用容器,而 2016 年仅为 3%。据阿里达摩院最新2021年科技趋势…

阿里云峰会 | 深化城市计算场景能力,为企业数智化建设提供助推力

在2020阿里云峰会上,阿里云边缘计算技术负责人杨敬宇表示:边缘计算将成为企业数智化进程中重要助推力,而构建城市计算是阿里云边缘计算的核心方向。在会上,杨敬宇还首次公开了智慧高速、云游戏、驾驶辅助等基于城市场景&#xff0…

nacos 适配达梦、人大金仓数据库

文章目录一、准备工作1. 阅读官网文档2. 下载源码,按官网更详细3. 下载达梦、人大金仓数据库驱动二、修改nacos源码2.1. 引入驱动依赖2.2. 引用数据库2.3. 修改配置2.4. 添加属性2.5. 指定驱动名称三、构建3.1. 进入源代码目录3.2. 执行构建3.3. 查看构建包3.4. 最后…

阿里云峰会 | 高并发扛不住、复杂查询慢、数据存不下?

阿里云峰会直播地址 2020年6月9日,“全速重构”2020阿里云线上峰会即将隆重召开。在此次峰会上,阿里云数据库重磅发布云原生分布式数据库 PolarDB-X 、云原生数据仓库AnalyticDB、数据库自治服务DAS、云数据库专属集群、图数据库GDB、云数据库Cassandra版…

软件设计师 - 超键、无损连接、函数依赖

1.闭包 在函数依赖集F下由α函数确定的所有属性的集合为F下α的闭包,记为α 。 闭包算法: result:α; while(result发生变化)dofor each 函数依赖β→γ in F dobeginif β∈result then result:result∪γ;end2.超键 方法一:函数依赖集F下…

赛题解析|初赛赛道三:服务网格控制面分治体系构建

首届云原生编程挑战赛正在报名中,初赛共有三个赛道,题目如下: 赛道一:实现一个分布式统计和过滤的链路追踪 赛道二:实现规模化容器静态布局和动态迁移 赛道三:服务网格控制面分治体系构建 立即报名&#…

使用 SQL 语句实现一个年会抽奖程序

作者 | 董旭阳 责编 | 张文头图 | CSDN 下载自视觉中国出品 | CSDN(ID:CSDNnews)年关将近,抽奖想必是大家在公司年会上最期待的活动了。如果老板让你做一个年会抽奖的程序,你会怎么实现呢?今天给大家介绍一…