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

springboot中使用async实现异步编程

目录

1.说明

2.实现原理

3.示例

4.总结


1.说明

@Async 是 Spring 框架提供的一个注解,用于标记方法为异步执行。被标记的方法将在调用时立即返回,而实际的方法执行将在单独的线程中进行。

@Async 注解有一个可选属性:指定要使用的特定线程池的 bean 名称

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {/*** 指定要使用的执行器(线程池)的限定符值*/String value() default "";
}

@Async 方法可以有以下返回类型:

  1. void:无返回值

  2. Future:返回 Future 对象,可用于获取异步执行结果

  3. CompletableFuture/ListenableFuture:更现代的异步结果处理方式

2.实现原理

基于 Spring AOP(面向切面编程)和任务执行器(TaskExecutor)框架。

3.示例

①启动类中开启异步支持

@EnableAsync  // 开启异步支持	
@SpringBootApplication	
public class Application {	public static void main(String[] args) {	SpringApplication.run(Application.class, args);	}	
}

EnableAsync有两个主要参数: mode及proxyTargetClass

@EnableAsync 通过 mode 属性来配置代理方式:

AdviceMode 枚举有两种选择:

  1. AdviceMode.PROXY (默认值) - 使用标准 Spring AOP 代理

    • 对接口使用 JDK 动态代理

    • 对类使用 CGLIB 代理

  2. AdviceMode.ASPECTJ - 使用 AspectJ 编织(weaving)

    • 需要额外的 AspectJ 依赖

    • 不需要接口也能代理

    • 可以代理更多方法类型(如 private 方法)

proxyTargetClass:指定使用CGLIB 代理还是JDK动态代理

proxyTargetClass = true 表示:

  • 强制使用 CGLIB 代理,即使目标类实现了接口

  • 代理目标类本身,而不是其实现的接口

  • 可以代理没有接口的类

默认行为(proxyTargetClass = false 或未指定)

  • 如果目标类实现了接口 → 使用 JDK 动态代理

  • 如果目标类没有实现接口 → 使用 CGLIB 代理

一般来说使用AdviceMode.PROXY及proxyTargetClass = true

②配置线程池

可以配置多个线程池

package com.example.demo1.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;@Configuration
public class ThreadPoolConfig {@Bean("executorPool1")public ThreadPoolTaskExecutor executorPool1() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);// 核心线程数executor.setMaxPoolSize(10);// 最大线程数executor.setQueueCapacity(100);// 队列容量executor.setKeepAliveSeconds(60);// 空闲线程的存活时间executor.setThreadNamePrefix("demo1-pool-");// 线程名称前缀executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 拒绝策略,让调用者线程自己执行被拒绝的任务// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); //默认的拒绝策略,会抛出RejectedExecutionException异常// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());// 拒绝策略,直接丢弃任务,不抛出异常// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());// 拒绝策略,丢弃队列中最老的任务,尝试再次提交当前任务executor.setWaitForTasksToCompleteOnShutdown(true); // 关闭时等待任务完成executor.setAwaitTerminationSeconds(60);           // 等待终止的最长时间(秒)return executor;}@Bean("executorPool2")public ThreadPoolTaskExecutor executorPool2() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);// 核心线程数executor.setMaxPoolSize(10);// 最大线程数executor.setQueueCapacity(100);// 队列容量executor.setKeepAliveSeconds(60);// 空闲线程的存活时间executor.setThreadNamePrefix("demo1-pool-");// 线程名称前缀executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 拒绝策略,让调用者线程自己执行被拒绝的任务// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); //默认的拒绝策略,会抛出RejectedExecutionException异常// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());// 拒绝策略,直接丢弃任务,不抛出异常// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());// 拒绝策略,丢弃队列中最老的任务,尝试再次提交当前任务executor.setWaitForTasksToCompleteOnShutdown(true); // 关闭时等待任务完成executor.setAwaitTerminationSeconds(60);           // 等待终止的最长时间(秒)return executor;}
}

 ③定义异步方法

package com.example.demo1.logic;import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;@Service
public class AsyncLogic {@Async("executorPool1")public CompletableFuture<String> process1(String item) {CompletableFuture<String> future = new CompletableFuture<>();try {System.out.println("线程名称:" + Thread.currentThread().getName());Thread.sleep(1000);future.complete("Processed: " + item);} catch (Exception e) {e.printStackTrace();future.completeExceptionally(e);}return future;}@Async("executorPool2")public Future<String> process2(String item) {try {System.out.println("线程名称:" + Thread.currentThread().getName());Thread.sleep(1000);return AsyncResult.forValue("Processed: " + item);} catch (Exception e) {e.printStackTrace();return AsyncResult.forExecutionException(e);}}@Async("executorPool1")public void process3(String item) {try {System.out.println("线程名称:" + Thread.currentThread().getName());Thread.sleep(1000);System.out.println("执行");} catch (Exception e) {e.printStackTrace();}}
}

④调用异步方法

package com.example.demo1;import com.example.demo1.logic.AsyncLogic;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.annotation.Async;import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;@SpringBootTest
public class AsyncTest {@Autowiredprivate AsyncLogic asyncLogic;@Testpublic void test114() {System.out.println("调用异步方法前");CompletableFuture<String> completableFuture = asyncLogic.process1("item");Future<String> item = asyncLogic.process2("item");asyncLogic.process3("item");System.out.println("执行其他操作,不阻塞主线程");try {System.out.println("获取异步任务结果,阻塞主线程");String result = completableFuture.get();System.out.println("异步任务结果1:" + result);String s = item.get();System.out.println("异步任务结果2:" + s);} catch (Exception e) {System.out.println("捕捉到异常");}System.out.println("调用异步方法后");}}

4.总结

1. 必须通过 Spring Bean 调用

❌ 错误:直接调用 this.asyncMethod()(同一类内调用不生效)。

✅ 正确:通过 @Autowired 注入自身或使用其他 Bean 调用。
2. 异常处理

默认静默吞异常,建议添加异常处理器:
异常时记录日志,并发送钉钉通知
3. 方法可见性

@Async 需作用于 public 方法,私有方法无效。
 

相关文章:

springboot中使用async实现异步编程

目录 1.说明 2.实现原理 3.示例 4.总结 1.说明 Async 是 Spring 框架提供的一个注解&#xff0c;用于标记方法为异步执行。被标记的方法将在调用时立即返回&#xff0c;而实际的方法执行将在单独的线程中进行。 Async 注解有一个可选属性&#xff1a;指定要使用的特定线程…...

【教程】MacBook 安装 VSCode 并连接远程服务器

目录 需求步骤问题处理 需求 在 Mac 上安装 VSCode&#xff0c;并连接跳板机和服务器。 步骤 Step1&#xff1a;从VSCode官网&#xff08;https://code.visualstudio.com/download&#xff09;下载安装包&#xff1a; Step2&#xff1a;下载完成之后&#xff0c;直接双击就能…...

初识 Three.js:开启你的 Web 3D 世界 ✨

3D 技术已经不再是游戏引擎的专属&#xff0c;随着浏览器技术的发展&#xff0c;我们完全可以在网页上实现令人惊艳的 3D 效果。而 Three.js&#xff0c;作为 WebGL 的封装库&#xff0c;让 Web 3D 的大门向更多开发者敞开了。 这是我开启这个 Three.js 专栏的第一篇文章&…...

基于大模型的病态窦房结综合征预测及治疗方案研究报告

目录 一、引言 1.1 研究背景与目的 1.2 研究意义 二、病态窦房结综合征概述 2.1 定义与病因 2.2 临床表现与分型 2.3 诊断方法 三、大模型在病态窦房结综合征预测中的应用 3.1 大模型介绍 3.2 数据收集与预处理 3.3 模型训练与优化 四、术前预测与准备 4.1 风险预…...

在 Ubuntu 下通过 Docker 部署 PSQL 服务器的详细技术博客

今天&#xff0c;需要部署一个密码管理器&#xff0c;突然要用到PSQL的服务器&#xff0c;所以就把部署的过程记录下来。 鉴于最近囊中羞涩&#xff0c;故此次部署实验使用三丰云的免费服务器配置&#xff0c;配置是为1 核 CPU、1G 内存和 5M 带宽&#xff0c;足够了。 以下是…...

【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(3)

1.问题描述&#xff1a; PC场景&#xff0c;青少年模式系统API不支持吗&#xff1f; 解决方案&#xff1a; PC场景&#xff0c;青少年模式系统API不支持&#xff0c;另外文档上的几个API也不支持。 2.问题描述&#xff1a; 华为一键登录 Beta7本地运行到手机可以拿到匿名手…...

地图与图层操作

地图文档本质上就是存储在磁盘上的地图&#xff0c;包括地理数据、图名、图例等一系列要素&#xff0c;当完成地图制作、图层要素标注及符号显示设置后&#xff0c;可以将其作为图层文件保存到磁盘中&#xff0c;在一个图层文件中&#xff0c;包括了定义如何在地图上描述地理数…...

starrocks split函数和trino split函数差异性

在trino419和starrocks3.2.8中分别执行下面这两条sql,出来的结果是不一样的 select split(,,,)[1] as t1 select coalesce(split(,,&#...

LeetCode算法题(Go语言实现)_33

题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 一、代码实现 func maxDepth(root *TreeNode) int {// 递归法&#xff08;后序遍历&#xff09;if root nil {return 0}leftDepth : maxDepth(r…...

go程序启动工具——cobra

以下是将“为什么很多 Go 程序启动都是用 Cobra”的内容转换为 Markdown 格式的文档&#xff1a; 为什么很多 Go 程序启动都是用 Cobra 在 Go 编程生态中&#xff0c;Cobra 是一个非常流行的命令行工具库&#xff0c;许多 Go 程序选择使用它来构建启动逻辑和命令行接口&#…...

Unet网络的Pytorch实现和matlab实现

文章目录 一、Unet网络简介1.1 输入图像1.2 编码器部分&#xff08;Contracting Path&#xff09;1.3 解码器部分&#xff08;Expanding Path&#xff09;1.4 最后一层&#xff08;输出&#xff09;1.5 跳跃连接&#xff08;Skip Connections&#xff09; 二、Unet网络的Pytorc…...

【合新通信】相控阵雷达RFoF方案的应用

一、相控阵雷达为何需要RFoF&#xff1f; 核心需求驱动 分布式部署&#xff1a;相控阵雷达&#xff08;AESA/PESA&#xff09;的T/R模块需分散布局&#xff08;如舰载雷达阵面、卫星载荷&#xff09;&#xff0c;传统同轴电缆导致重量和损耗剧增。高频段挑战&#xff1a;X/Ku/…...

关于点卷积

&#x1f9e0; 什么是点卷积&#xff1f; 点卷积&#xff08;Pointwise Convolution&#xff09; 是一种特殊类型的卷积操作&#xff0c;其基本特点是卷积核的大小为 1 1 1 \times 1 11。与传统的卷积操作&#xff08;如 3 3 3 \times 3 33 或 5 5 5 \times 5 55 卷积核…...

原理图输出网表及调入

一、输出网表操作步骤 &#xff08;1&#xff09;选中.dsn文件&#xff0c;选者N或进入tools下拉列表选择Creat Netlists &#xff08;2&#xff09;导出网表后的文件 二、网表的导入 &#xff08;1&#xff09;执行菜单命令“File-Import-Logic/netlist”&#xff0c;将原理…...

python基础12 模块/库的引用

在软件的设计中&#xff0c;经常提及到解耦的概念&#xff0c;即模块和模块之间的功能尽可能独立&#xff0c;减少不必要的关联。所以在实际项目中&#xff0c;我们经常会将一个工程拆解成很多不同的功能模块&#xff0c;以实现更优的设计并满足团队开发的要求。 有了模块的概…...

TDengine JAVA 语言连接器

简介 本节简介 TDengine 最重要且使用最多的连接器, 本节内容是以教科书式方式列出对外提供的接口及功能及使用过程中要注意的技术细节&#xff0c;大家可以收藏起来做为今后开发 TDengine 的参考资料。 taos-jdbcdriver 是 TDengine 的官方 Java 语言连接器&#xff0c;Java…...

【NLP 55、实践 ⑬ LoRA完成NER任务】

目录 一、数据文件 二、模型配置文件 config.py 三、数据加载文件 loader.py 1.导入文件和类的定义 2.初始化 3.数据加载方法 代码运行流程 4.文本编码 / 解码方法    ① encode_sentence()&#xff1a; ② decode()&#xff1a; 代码运行流程 ③ padding()&#xff1a; 代码…...

【蓝桥杯】Python大学A组第十五届省赛

1.填空题 1.1.拼正方形 问题描述 小蓝正在玩拼图游戏,他有个的方块和个的方块,他需要从中挑出一些来拼出一个正方形。 比如用个和个的方块可以拼出一个的正方形;用个的方块可以拼出一个的正方形。 请问小蓝能拼成的最大的正方形的边长为多少。 import math # 2*2的个数 a =…...

小球反弹(蓝桥杯C语言)

有一长方形&#xff0c;长为 343720343720 单位长度&#xff0c;宽为 233333233333 单位长度。在其内部左上角顶点有一小球 (无视其体积)&#xff0c;其初速度如图所示且保持运动速率不变&#xff0c;分解到长宽两个方向上的速率之比为 dx:dy15:17dx:dy15:17。小球碰到长方形的…...

Redis底层数据结构?编码与底层数据结构的映射?

Redis底层数据结构 一、简单动态字符串&#xff08;SDS&#xff09; 结构&#xff1a; struct sdshdr {int len; // 已使用字节长度 int free; // 未使用字节长度 char buf[]; // 字节数组&#xff08;兼容C字符串&#xff09; };特点&#xff1a; 二进制安全&#…...

linux环境下的硬盘分区格式化工具介绍 fdisk,gdisk,parted,cfdisk,cgdisk,sfdisk,gparted 笔记250407

linux环境下的硬盘分区格式化工具介绍 fdisk,gdisk,parted,cfdisk,cgdisk,sfdisk,gparted 笔记250407 以下是 Linux 系统中常用的 硬盘分区与格式化工具&#xff0c;涵盖命令行和图形界面工具&#xff0c;按功能分类整理&#xff1a; 一、分区管理工具 1. 命令行工具 工具功能…...

HarmonyOS-ArkUI Ability进阶系列-UIAbility与各类Context

UIAbility及相关类关系 一个模块编译的时候会出一个HAP包&#xff0c; 每一个HAP包在运行时都对应一个AbilityStage。 AbilityStage持有一个AbilityStageContext一个APP&#xff0c; 有时候会有很多个HAP包&#xff0c; 至少一个。 一个APP运行时&#xff0c;对应的是我们的App…...

前端入门之CSS

CSS: HTML负责定义页面结构;JS负责处理页面逻辑和点击事件;CSS负责用于描述 HTML 元素的显示方式,通过 CSS 可以控制颜色、字体、布局等。 核心语法: 选择器: 类选择器主要用于选中需要添加样式的 HTML 元素。主要分为:类选择器(.class-name { ... })、标签选择器(…...

JavaScript逆向WebSocket协议解析与动态数据抓取

在JavaScript逆向工程中&#xff0c;WebSocket协议的解析和动态数据抓取是关键技能。本文将结合Fiddler、Charles Proxy和APIfox工具&#xff0c;详细讲解如何解析WebSocket协议并抓取动态数据。 一、WebSocket协议解析 &#xff08;一&#xff09;WebSocket协议的基本概念 …...

剑指Offer(数据结构与算法面试题精讲)C++版——day4

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day4 题目一&#xff1a;和为k的子数组题目二&#xff1a;0和1个数相同的子数组题目三&#xff1a;左右两边子数组的和相等 题目一&#xff1a;和为k的子数组 结合前面着重阐述的双指针法这一经典的算法技巧&…...

从代码学习深度学习 - NLP之文本预处理 PyTorch版

文章目录 前言1. 文本预处理理论知识1.1 文本清洗与标准化1.2 分词(Tokenization)1.3 词频统计与词汇表构建1.4 序列表示与批次生成1.5 预处理的意义2. 文本预处理的核心代码解析2.1 读取数据集:`read_time_machine`2.2 分词处理:`tokenize`2.3 词频统计:`count_corpus`2.…...

WebRTC技术简介及应用场景

写在前面 本文是参考稀土掘金的文章,整理得出,版权归原作者所有!参考链接请点击跳转 WebRTC&#xff08;Web Real-Time Communication&#xff09; 是一项开源技术&#xff0c;允许浏览器和移动应用直接进行实时音视频通信和数据传输&#xff0c;无需安装插件或第三方软件。它…...

介绍几种创意登录页(含完整源码)

今天为大家收集了几种不同风格的登录页&#xff0c;搭配动态渐变背景&#xff0c;效果绝对惊艳&#xff01; CSS3实现动态渐变玻璃拟态登录页 一、开篇语 纯CSS实现当下最火的玻璃拟态(Morphism)风格登录页&#xff0c;搭配动态渐变背景&#xff0c;效果绝对惊艳&#xff01; …...

git分布式控制工具详解

1. 版本控制器的方式 1.1 集中式版本控制工具 特点&#xff1a; 版本库集中存放在中央服务器必须联网才能工作&#xff08;局域网/互联网&#xff09;个人修改后提交到中央版本库 举例&#xff1a;SVN、CVS 1.2 分布式版本控制工具 特点&#xff1a; 无"中央服务器&qu…...

Uni-app入门到精通:uni-app的基础组件

1、view view是容器组件&#xff0c;类似于HTML中的<div></div>标签&#xff0c;用于包裹各种元素内容&#xff0c;是页面布局常用的组件。view组件的属性如下 属性类型默认值说明hover-classStringnone指定按下去的样式类。当hover-class"none"时&…...