当前位置: 首页 > news >正文

spring异步框架使用教程

背景

在需求开发过程中,为了提升效率,很容易就会遇到需要使用多线程的场景。这个时候一般都会选择建一个线程池去专门用来进行某一类动作,这种任务到来的时候往往伴随着大量的线程被创建调用。而还有另外一种场景是整个任务的执行耗时比较长,但又不适合起多线程去运行,只能后台起一个异步线程去慢慢跑。这个时候就需要一个公共的线程池。

可选方案

总体思想就是要有一个全局可用的线程池,可以用来执行一些零散的任务。

方案一

自定义一个全局的线程池,需要异步操作的就调用。这种方法好处是实现简单,并且调用起来也简单,直接当成一个方法就可以了。但需要同模块项目(或者导入了模块)才能使用。

方案二

使用Spring自带的注解@Async实现异步。这种方法的好处是注解可以跨模块使用,因为线程池对象会被注入容器,整个服务共用。而且更大的好处是使用简单,使用者只需要给所需异步操作的方法加上@Async(“beanName”)即可。其中beanName是指注入容器的对象的名称,也可以不加参数,不加参数代表使用默认线程池。

考虑到便捷性和新手友好性,选择了方案二。

实现(注意看我的调用的结构,可以避免循环依赖)

controller->async->service √
controller->service->async->service ×,这样会出现循环依赖

1.创建线程池配置类

/**
*	必须加上@EnableAsync注解
*/
@EnableAsync
@Configuration
public class TaskPoolConfig {/***	可以多创建几个bean注入容器,根据bean不同用来执行不同类型的任务*/@Bean("taskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//核心线程池大小executor.setCorePoolSize(16);//最大线程数executor.setMaxPoolSize(20);//配置队列容量,默认值为Integer.MAX_VALUEexecutor.setQueueCapacity(99999);//活跃时间executor.setKeepAliveSeconds(60);//线程名字前缀executor.setThreadNamePrefix("asyncServiceExecutor -");//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行executor.setAwaitTerminationSeconds(60);//等待所有的任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}@Bean("taskExecutor2")public Executor taskExecutor2() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//核心线程池大小executor.setCorePoolSize(16);//最大线程数executor.setMaxPoolSize(20);//配置队列容量,默认值为Integer.MAX_VALUEexecutor.setQueueCapacity(99999);//活跃时间executor.setKeepAliveSeconds(60);//线程名字前缀executor.setThreadNamePrefix("asyncServiceExecutor -");//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行executor.setAwaitTerminationSeconds(60);//等待所有的任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}
}

2.使用异步

异步类:

public interface AsyncService {void test();
}
@Slf4j
@Service
public class AsyncServiceImpl implements AsyncService {@Autowiredprivate TestService testService;//这里的参数是只bean的名称,不填则使用默认的线程池。如果这个注解放在类上,代表这个类里面的全部方法都走异步@Async("taskExecutor")void test(){testService.todo();}@Async("taskExecutor2")void test2(){testService.todo2();}
}

业务类:

public interface TestService {void todo();void todo2();
}
@Slf4j
@Service
public class TestServiceImpl implements TestService{void todo(){LocalDateTime dateTime=LocalDateTime.now();log.info("已经进入异步方法,现在时间:{},睡三秒",dateTime);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}dateTime=LocalDateTime.now();log.info("三秒后时间为:{}",dateTime);}void todo2(){}
}

测试类:

@Slf4j
@RestController
public class TestController {@Autowiredprivate AsyncService asyncService;@RequestMapping("/test")public void test(){asyncService.test();LocalDateTime dateTime=LocalDateTime.now();log.info("这是主线程,现在时间为:{}",dateTime);}
}

结果:成功
在这里插入图片描述

坑点

1.异步失效

如果一个类里面有两个方法A、B,方法B添加了异步注解,方法A调用方法B,异步不会生效。
查了一下,好像是因为异步注解的实现用到了动态代理,而一个类内部方法的调用不会走代理,也就没法实现异步。
因此,建议把异步都放在一个专门的异步类里面,这个类的方法只用来实现异步,方法内部再去调用真正的业务逻辑方法。

2.循环依赖

正常来说,A类中注入B类对象,B类中再注入A类对象。这种情况在代码中并不会发生循环依赖。而在异步注解中会出现循环依赖,因为异步注解底层实现用的是动态代理。

相关文章:

spring异步框架使用教程

背景 在需求开发过程中,为了提升效率,很容易就会遇到需要使用多线程的场景。这个时候一般都会选择建一个线程池去专门用来进行某一类动作,这种任务到来的时候往往伴随着大量的线程被创建调用。而还有另外一种场景是整个任务的执行耗时比较长…...

【数学建模】清风数模正课3 插值算法

插值算法 在数模比赛中,很多类型的题目都需要根据已知的函数点进行数据分析和模型处理; 当此时题目所给的数据较少时,我们就无法进行准确科学的分析,所以需要更多的数据,也就是函数点; 这就需要使用数学…...

什么是eval()?eval是用来干什么的?

一、什么是eval()? eval() 是 JavaScript 中的一个全局函数,用于解析并执行传递给它的字符串作为 JavaScript 代码。 二、eval()是用来干什么的? 当调用 eval() 时,它会将传入的字符串参数视为 JavaScript 代码,并在调用位置执…...

JavaScript-console:JavaScript控制台(Console)常用方法

一、理解 console JavaScript 控制台(console)是一个开发人员在编写 JavaScript 代码时常用的工具。它是浏览器提供的一种界面,让开发人员能够追踪代码执行的状态和结果。JavaScript 控制台可以记录代码输出的信息、警告和错误,并…...

Nginx配置前后端分离

后端地址 1.本地环境 curl --request GET \--url http://localhost:8080/by-admin/captchaImage \--header Authorization: Bearer d7a035d9-b30c-4ca5-8951-8cec90607943确认后端 ip 端口 上下文 2.测试环境 部署到测试环境可能是 换成内网ip和内网服务端口(ip、端口 可能会…...

rabbitmq的发布确认

生产者将信道设置成 confirm 模式,一旦信道进入 confirm 模式, 所有在该信道上面发布的 消息都将会被指派一个唯一的 ID (从 1 开始),一旦消息被投递到所有匹配的队列之后,broker 就会发送一个确认给生产者(包含消息的唯一 ID)&…...

RISC-V公测平台发布· CoreMark测试报告

一. CoreMark简介 CoreMark是一款用于评估CPU性能的基准测试程序,它包含了多种不同的计算任务,包括浮点数、整数、缓存、内存等方面的测试。CoreMark的测试结果通常被用来作为CPU性能的参考,它可以帮助开发人员和系统管理员评估不同处理器和…...

模型微调(fine-tune)

一、关于模型微调的一些基础知识 1、模型微调(fine-tune) 微调(fine-tune)通过使用在大数据上得到的预训练好的模型来初始化自己的模型权重,从而提升精度。这就要求预训练模型质量要有保证。微调通常速度更快、精度更高。当然,自己…...

云农场种植:互联网+智慧牧场,为农业注入新的活力和创新

随着科技的不断发展,数字化农业正逐渐成为现代农业的趋势。传统农业面临着土地资源有限、劳动力不足等问题,而云农场种植模式通过数字化技术的运用,互联网养殖着重于“绿色、特色产品和智慧生态”,通过建立“线上养殖线下托养线上…...

Hadoop学习一(初识大数据)

目录 一 什么是大数据? 二 大数据特征 三 分布式计算 四 Hadoop是什么? 五 Hadoop发展及版本 六 为什么要使用Hadoop 七 Hadoop vs. RDBMS 八 Hadoop生态圈 九 Hadoop架构 一 什么是大数据? 大数据是指无法在一定时间内用常规软件工具对其内…...

linux定时备份MySQL数据库循环删除前30天的备份文件

linux定时备份MySQL数据库循环删除前30天的备份文件 一、 检查有没安装crond,如果没有,先安装 1、先检查一下有没有cron rpm -qa|grep cron如果输入上面命令有如下显示,则不需要安装 2、没有安装的话,就使用一下命令安装 yum -y install …...

不加电透明屏:在场景化应用中,有哪些特点和优点?

不加电透明屏是一种新型的显示技术,它可以在不需要电源的情况下显示图像和文字。 这种屏幕的原理是利用光的折射和反射来实现显示效果,而不需要通过电流来激发像素点。 不加电透明屏的最大优点是节能环保。传统的显示屏需要消耗大量的电能来显示图像&a…...

全球公链进展| Shibarium已上线;opBNB测试网PreContract硬分叉;Sui 主网 V1.7.1 版本

01 ETH 以太坊最新一次核心开发者执行会议:讨论 Devnet 8 更新、ElP-4788、Holesky 测试网等 以太坊核心开发者 Tim Beiko 总结最新一次以太坊核心开发者执行会议(ACDE),讨论内容包括 Devnet 8 更新、ElP-4788、Holesky 测试网、…...

CSS中的display属性有哪些值?它们的作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS display 属性的不同取值和作用1. block2. inline3. inline-block4. none5. flex6. grid7. table、table-row、table-cell8. list-item9. inline-table、table-caption、table-column 等 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#x…...

ELKstack-日志收集案例

由于实验环境限制,将 filebeat 和 logstash 部署在 tomcat-server-nodeX,将 redis 和 写 ES 集群的 logstash 部署在 redis-server,将 HAproxy 和 Keepalived 部署在 tomcat-server-nodeX。将 Kibana 部署在 ES 集群主机。 环境:…...

基于GPT-4和LangChain构建云端定制化PDF知识库AI聊天机器人

参考: GitHub - mayooear/gpt4-pdf-chatbot-langchain: GPT4 & LangChain Chatbot for large PDF docs 1.摘要: 使用新的GPT-4 api为多个大型PDF文件构建chatGPT聊天机器人。 使用的技术栈包括LangChain, Pinecone, Typescript, Openai和Next.js…...

Python可视化工具分享

今天和大家分享几个实用的纯python构建可视化界面服务,比如日常写了脚本但是不希望给别人代码,可以利用这些包快速构建好看的界面作为服务提供他人使用。有关于库的最新更新时间和当前star数量。 streamlit (23.3k Updated 2 hours ago) Streamlit 可让…...

ethers.js:构建ERC-20代币交易的不同方法

在这篇文章中,我们将探讨如何使用ethers.js将ERC-20令牌从一个地址转移到另一个地址 Ethers是一个非常酷的JavaScript库,它能够发送EIP-1559事务,而无需手动指定气体属性。它将确定gasLimit,并默认使用1.5 Gwei的maxPriorityFeePerGas,从v5.6.0开始。 此外,如果您使用签名…...

[实践篇]13.23 QNX环境变量profile

一,profile简介 /etc/profile或/system/etc/profile是qnx侧的设置环境变量的文件,该文件适用于所有用户,它可以用作以下情形: 设置HOMENAME和SYSNAME环境变量设置PATH环境变量设置TMPDIR环境变量(/tmp)设置PCI以及IFS_BASE等环境变量等文件内容示例如下: /etc/profile…...

HDLBits-Verilog学习记录 | Getting Started

Getting Started problem: Build a circuit with no inputs and one output. That output should always drive 1 (or logic high). 答案不唯一,仅共参考: module top_module( output one );// Insert your code hereassign one 1;endmodule相关解释…...

龙虎榜——20250610

上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

OpenLayers 可视化之热力图

注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...