在Spring Boot中隔离@Async异步任务的线程池
在异步任务执行的时候,我们知道其背后都有一个线程池来执行任务,但是为了控制异步任务的并发不影响到应用的正常运作,我们需要对线程池做好相关的配置,以防资源过度使用。这个时候我们就考虑将线程池进行隔离了。
那么我们为啥要隔离@Async异步任务的线程池?
-
控制资源:通过隔离异步任务的线程池,可以更好地控制系统的资源使用。不同类型的异步任务可能对系统资源的需求不同,例如某些任务可能需要更多的线程数或更大的队列容量。通过隔离线程池,可以为每种类型的任务分配适当的资源,避免资源争用和过度消耗。
-
优化性能:隔离异步任务的线程池可以帮助优化系统的性能。如果所有的异步任务共享同一个线程池,当某个任务出现阻塞或执行时间过长时,可能会影响其他任务的执行。通过隔离线程池,可以确保每个任务都有独立的线程池资源,提高系统的并发能力和响应性能。
-
业务隔离:有时候,不同的业务逻辑可能需要不同的异步任务处理方式。通过隔离线程池,可以为每个业务逻辑定义独立的线程池,以满足不同业务的需求。例如,某些任务可能需要更高的优先级或更短的超时时间,而另一些任务可能需要更大的线程池容量。通过隔离线程池,可以更好地管理和调整每个业务逻辑的异步任务执行环境。
下面看一个demo:
demo
-
创建自定义的线程池:首先,你可以创建一个自定义的线程池,用于处理
@Async
注解标记的异步任务。可以使用ThreadPoolTaskExecutor
类来创建线程池。@Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer {@Bean(name = "asyncTaskExecutor")public Executor asyncTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 配置线程池属性executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);executor.setThreadNamePrefix("AsyncTask-");executor.initialize();return executor;}@Overridepublic Executor getAsyncExecutor() {return asyncTaskExecutor();} }
在上述示例中,我们创建了一个名为
asyncTaskExecutor
的线程池,并配置了核心线程数、最大线程数、队列容量等属性。 -
在异步任务方法上指定线程池:接下来,你可以在需要异步执行的方法上使用
@Async
注解,并通过value属性指定要使用的线程池。@Service public class MyService {@Async("asyncTaskExecutor")public void asyncMethod() {// 异步任务的具体逻辑} }
在上述示例中,我们使用
@Async("asyncTaskExecutor")
注解将asyncMethod()
方法标记为异步任务,并指定了使用名为asyncTaskExecutor
的线程池。
实际案例
记得在启动类中添加@EnableAsync
注解呀
我们来初始化多个线程池:
@EnableAsync
@Configuration
public class TaskPoolConfig {@Beanpublic Executor taskExecutor1() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);//使用线程名前缀,可以用来观察顺序executor.setThreadNamePrefix("executor-1-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}@Beanpublic Executor taskExecutor2() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(2);executor.setQueueCapacity(10);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("executor-2-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}
}
接下来创建一个异步任务,然后指定要使用线程池名字。
@Slf4j
@Component
public class AsyncTasks {public static Random random = new Random();@Async("taskExecutor1")public CompletableFuture<String> doTaskOne(String taskNo) throws Exception {log.info("开始任务:{}", taskNo);long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);return CompletableFuture.completedFuture("任务完成");}@Async("taskExecutor2")public CompletableFuture<String> doTaskTwo(String taskNo) throws Exception {log.info("开始任务:{}", taskNo);long start = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end = System.currentTimeMillis();log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);return CompletableFuture.completedFuture("任务完成");}}
创建一个测试类:
@Slf4j
@SpringBootTest
public class ApplicationTests {@Autowiredprivate AsyncTasks asyncTasks;@Testpublic void test() throws Exception {long start = System.currentTimeMillis();// 线程池1CompletableFuture<String> task1 = asyncTasks.doTaskOne("1");CompletableFuture<String> task2 = asyncTasks.doTaskOne("2");CompletableFuture<String> task3 = asyncTasks.doTaskOne("3");// 线程池2CompletableFuture<String> task4 = asyncTasks.doTaskTwo("4");CompletableFuture<String> task5 = asyncTasks.doTaskTwo("5");CompletableFuture<String> task6 = asyncTasks.doTaskTwo("6");// 一起执行CompletableFuture.allOf(task1, task2, task3, task4, task5, task6).join();long end = System.currentTimeMillis();log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");}}
在上面的单元测试中,一共启动了6个异步任务,前三个用的是线程池1,后三个用的是线程池2。
先不执行,根据设置的核心线程2和最大线程数2,我们来猜猜线程的执行顺序。
-
线程池1的三个任务,task1和task2会先获得执行线程,然后task3因为没有可分配线程进入缓冲队列
-
线程池2的三个任务,task4和task5会先获得执行线程,然后task6因为没有可分配线程进入缓冲队列
-
任务task3会在task1或task2完成之后,开始执行
-
任务task6会在task4或task5完成之后,开始执行
执行结果:
通过以上步骤,你可以实现对@Async
异步任务的线程池进行隔离。这样可以根据需要创建多个线程池,并为不同的异步任务指定不同的线程池,以实现任务之间的隔离和资源控制。通过隔离@Async
异步任务的线程池,可以实现对系统资源的控制、性能的优化和业务逻辑的隔离。这样可以提高系统的稳定性、可伸缩性和灵活性,更好地满足不同业务场景下的需求。
相关文章:

在Spring Boot中隔离@Async异步任务的线程池
在异步任务执行的时候,我们知道其背后都有一个线程池来执行任务,但是为了控制异步任务的并发不影响到应用的正常运作,我们需要对线程池做好相关的配置,以防资源过度使用。这个时候我们就考虑将线程池进行隔离了。 那么我们为啥要…...

FFmpeg架构全面分析
一、简介 它的官网为:https://ffmpeg.org/,由Fabrice Bellard(法国著名程序员Born in 1972)于2000年发起创建的开源项目。该人是个牛人,在很多领域都有很大的贡献。 FFmpeg是多媒体领域的万能工具。只要涉及音视频领…...
OAuth(开放授权)介绍
OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另一服务提供商上的信息,而无需将用户名和密码直接暴露给第三方应用。这个过程提供了一种安全的授权方式,常用于允许用户让第三方应用访问例如邮箱…...
Online ddl和replace ddl
在这个之前我们先来了解两种文件类型 1. .ibd文件 表数据文件,存储了表的数据和索引信息,从Mysql8开始表定义信息,从.frm文件改为.dcl文件存储,而表数据和索引信息仍然储存在.ibd文件,.idb文件通常在书籍库目录下。 …...

WEB渗透—反序列化(九)
Web渗透—反序列化 课程学习分享(课程非本人制作,仅提供学习分享) 靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场 课程地址:PHP反序列化漏洞学习_哔哩哔_…...

蓝桥杯day02——第三大的数
题目 给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。 示例 1: 输入:[3, 2, 1] 输出:1 解释:第三大的数是 1 。 示例 2: 输入:[1, 2] 输出&…...
linux shell中set -e命令的作用
set -e 是一个在shell脚本中常用的命令,它的含义是在脚本执行过程中,如果出现任何一个命令的执行结果不是零(即命令执行失败),则立即退出整个脚本。 set -e 的用途是在脚本中进行错误处理和控制流程。通过设置set -e&…...
linux shell 字符替换命令
sed 文本 2.txt 内容如下: 1 2 3 4 511 121abcabcc1.替换文本指定字符或字符串,不更改原文件 将文本内容替换并输出,但不直接在原文档中修改: sed "s/旧字符串/新字符串/g" 文档 范例,将文本中的 1 替换为 b rootheihei:/# sed &…...

Vue3生命周期函数(简述题)
1.图示 2.说明 3.补充 1.在vue3组合式API中,我们需要将生命周期函数先导入,然后才能使用。 import {onMounted} from vue2.beforeCreate和created被setup()方法所代替...
11月29日,每日信息差//雷军个人向武汉大学捐赠13亿元现金//看电视默认设置新规一览:开机广告不超 5 秒、不设置一键付费
🎖 继长安汽车后,蔚来将与吉利控股达成换电业务合作 🎄 中国飞鹤入选工信部质量提升典型案例 🎆 雷军个人向武汉大学捐赠13亿元现金 🎇 奢侈品电商Farfetch或将私有化 🎁 亚马逊云科技宣布推出Amazon Q ✨ …...

融资经理简历模板
这份简历内容,以综合柜员招聘需求为背景,我们制作了1份全面、专业且具有参考价值的简历案例,大家可以灵活借鉴。 融资经理简历在线编辑下载:百度幻主简历 求职意向 求职类型:全职 意向岗位:融资经理 …...

iptables防火墙之SNAT与DNET
NAT 1.SNAT:让内网可以访问外网 2.DNAT:让外网可以访问到内网的机器 网关服务器,要开启路由功能 内核功能: sysctl -a 列出所有参数 内核参数,然后grep可以查看到默认的内核参数 内核参数配置文件 /etc/sysctl.…...
mysql使用--备份与恢复
1.mysqldump 1.1.使用mysqldump备份数据 1.1.1.备份指定数据库中的指定表 如:mysqldump [其他选项] 数据库名 [表1名 表2名 …] 如:mysqldump -uroot -hlocalhost -p1234 database1 student_score > student_score.sql 上述采用-u和-p完成用户登录&am…...

【vue实战项目】通用管理系统:信息列表,信息录入
本文为博主的vue实战小项目系列中的第六篇,很适合后端或者才入门的小伙伴看,一个前端项目从0到1的保姆级教学。前面的内容: 【vue实战项目】通用管理系统:登录页-CSDN博客 【vue实战项目】通用管理系统:封装token操作…...
【驱动】SPI驱动分析(六)-RK SPI驱动分析
前言 Linux的spi接口驱动实现目录在kernel\drivers\spi下。这个目录和一些层次比较明显的驱动目录布局不同,全放在这个文件夹下,因此还是只好通过看Kconfig 和 Makefile来找找思路 先看Makefile,里面关键几行: obj-$(CONFIG_SPI…...

【Linux】基础IO--文件基础知识/文件操作/文件描述符
文章目录 一、文件相关基础知识二、文件操作1.C语言文件操作2.操作系统文件操作2.1 比特位传递选项2.2 文件相关系统调用2.3 文件操作接口的使用 三、文件描述符fd1.什么是文件描述符2.文件描述符的分配规则 一、文件相关基础知识 我们对文件有如下的认识: 1.文件 …...

Intellij IDEA 的安装和使用以及配置
IDE有很多种,常见的Eclipse、MyEclipse、Intellij IDEA、JBuilder、NetBeans等。但是这些IDE中目前比较火的是Intellij IDEA(以下简称IDEA),被众多Java程序员视为最好用的Java集成开发环境,今天的主题就是IDEA为开发工…...

Zynq-Linux移植学习笔记之67- 国产ZYNQ上通过GPIO模拟MDC/MDIO协议
1、背景介绍 模块上有9个PHY,其中两个PHY通过ZYNQ PS端的MDIO总线连接,其余7个PHY单独通过GPIO进行控制,需要实现GPIO模拟MDC/MDIO协议。 2、vivado工程设计 vivado工程内为每个PHY建立两个GPIO IP核,分别用来代表MDC和MDIO&…...
Zookeeper(一)在WSL单机搭建Zookeeper伪集群
目录 Zookeeper1 启动单个Zookeeper实例1.1 下载Zookeeper安装包并解压1.2 添加环境变量1.3 修改默认配置1.4 新建数据存储目录和日志目录1.5 启动Zookeeper1.6 停止Zookeeper 2 搭建Zookeeper集群2.1 新建集群目录2.2 配置环境变量2.3 创建节点目录2.4 修改配置2.5 创建节点ID…...
QT(18):QString
目录 QStringQTypedArrayDataQTypedArrayDataQLatin1StringQStringLiteral乱码 QStringRef QString QString 存储16位QChar的字符串,其中每个QChar对应一个 UTF-16代码单元。QString 使用(写入时复制copy-on-write)来减少内存使用并避免不必…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...