springboot 异步 @Async 的日常使用及失效场景

文章目录

  • springboot 异步 @Async 的日常使用
    • 引言
    • 一、@Async 使用位置
    • 二、@Async 使用
    • 三、注解 @Async 失效的情况
      • (1)调用同一个类中的异步方法(内部调用)
      • (2)未使用 @EnableAsync 注解
      • (3)注解@Async的方法不是public方法
      • (4)返回值错误
      • (5)方法用static修饰了
      • (6)类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
      • (7)方法用final修饰
      • (8)业务类没加@Service注解

springboot 异步 @Async 的日常使用

本文主要介绍 @Async 在日常开发中的使用和注意点(@Async 注解失效场景),不做原理的解释说明。

引言

在 java 中很多业务涉及到异步线程,比如在业务流处理时,需要发短信发邮件通知用户,或者需要上传一些文件资源到其他服务器这种耗时的操作。
这种比较耗时的操作如果都在主线程里处理会阻塞整理流程,而且我们也不需要等待处理结果之后再进行下一步操作,这时候就可以使用异步线程进行处理,这样主线程不会因为这些耗时的操作而阻塞,保证主线程的流程可以正常进行。

一、@Async 使用位置

  1. 在方法上使用该@Async注解,表明该方法是一个异步任务
  2. 在类上面使用该@Async注解,表明该类中的所有方法都是异步任务

二、@Async 使用

在 Springboot 中使用 @Async:

  • @Async 注解在使用时,如果不指定线程池的名称,则使用默认的线程池,Spring默认的线程池为 SimpleAsyncTaskExecutor
  • 方法上一旦标记了这个 @Async 注解,当其它线程调用这个方法时,就会开启一个新的子线程去异步处理该业务逻辑。
  • 启动类中增加 @EnableAsync 注解

代码示例:

本文不做新配置,全部使用默认的线程池及配置。

(1)创建 AsyncService 写异步方法

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {

    @Async
    public void Async() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println("程序睡眠结束");

    }

(2)编写业务层 AsyncTestService

package com.ruoyi.system.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncTestService {
    @Autowired
    private AsyncService asyncService;


    public String testSync() throws InterruptedException {
        System.out.println("开始进入方法");
        System.out.println("进行时");
        System.out.println("正在进行时");
		asyncService.Async();
        return "成功";
    }
}

(3)编写接口 AsyncTestController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/async/lost")
public class AsyncTestController {

    @Autowired
    private AsyncTestService asyncTestService;

    @RequestMapping(value = "/test", method = {RequestMethod.POST})
    public String testAsync() throws InterruptedException {
        asyncTestService.testSync();
        System.out.println("调用Controller控制器结束");
        return "成功";
    }
}

postman 测试:

从下图测试结果可知,打印语句 “调用Controller控制器结束” 在 “程序睡眠结束” 之前执行,异步实现成功,没有影响到主线程的任务。
在这里插入图片描述

三、注解 @Async 失效的情况

(1)调用同一个类中的异步方法(内部调用)

从上面的 @Async 使用我们看到,添加注解的异步方法在一个单独的类 AsyncService 中,然后注入到 AsyncTestService 中进行调用。如果异步方法和调用的方法在同一个类中,还会正常进行异步调用吗?

AsyncTestService 代码如下:

@Service
public class AsyncTestService {

    public String testSync() throws InterruptedException {
        System.out.println("开始进入方法");
        System.out.println("进行时");
        System.out.println("正在进行时");
        Async();
        return "成功";
    }

    @Async
    public void Async() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println("程序睡眠结束");

    }
}

postman 测试:

在这里插入图片描述
如上图所示,打印语句 “调用Controller控制器结束” 在 “程序睡眠结束” 之后执行,说明异步并没有生效,程序还是走了主线程。

这是因为 @Async注解是通过aop代理实现的,需要通过JDK动态代理或者cglib,生成代理对象。异步的功能,是在代理对象中增加的,我们必须调用代理对象的 testSync() 方法才行。而在类中直接进行方法的内部调用,在 testSync() 方法中调用Async()方法,调用的是该类原对象的Async方法,相当于调用了this.Async()方法,而并非AsyncTestService 代理类的 Async() 方法。 因此,像这种内部方法调用,@Async注解的异步功能会失效。

要想在同一个类中调用异步方法,需要使用 ApplicationContext 获得到该类。

AsyncTestService 代码如下:

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncTestService {

    @Autowired
    private ApplicationContext applicationContext;


    public String testSync() throws InterruptedException {
        AsyncTestService asyncBean = applicationContext.getBean(AsyncTestService.class);
        System.out.println("当前对象是否是代理对象:" + AopUtils.isAopProxy(asyncBean));
        System.out.println("是否是cglib代理对象:" + AopUtils.isCglibProxy(asyncBean));
        System.out.println("是否是jdk代理对象:" + AopUtils.isJdkDynamicProxy(asyncBean));
        System.out.println(asyncBean == this);
        asyncBean.Async();
        return "成功";
    }

    @Async
    public void Async() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println("程序睡眠结束");

    }
}

postman 测试:

打印控制器语句在前,异步实现成功。
在这里插入图片描述

(2)未使用 @EnableAsync 注解

在 Springboot 中要开启@Async注解异步的功能,需要在项目的启动类,或者配置类上,使用@EnableAsync注解。

@EnableAsync注解相当于一个开关,控制是否开启@Async注解异步的功能,默认是关闭的。

@EnableAsync
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

(3)注解@Async的方法不是public方法

异步的方法必须是 public修饰的,否则 aop 代理异常,异步失效。

(4)返回值错误

注解 @Async 的返回值只能为 voidFuture

(5)方法用static修饰了

使用@Async注解声明的方法,必须是能被重写的,很显然static修饰的方法,是类的静态方法,是不允许被重写的。
因此这种情况下,@Async注解的异步功能会失效。

(6)类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象

(7)方法用final修饰

(8)业务类没加@Service注解

================================

(时间宝贵,分享不易,非常感谢您的捐赠回馈)

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Laravel8.5+微信小程序实现京东商城秒杀方案

一、商品秒杀涉及的知识点 鉴权策略封装掊口访问频次限制小程序设计页面防抖接口调用订单创建事务使用超卖防御 二、订单库存系统方案(3种) 下单减库存 优点是库存和订单的强一致性,商品不会卖超,但是可能导致恶意下单&#xff…

三角网格体的光滑性问题

三角网格体的光滑性问题 在计算机图形学和计算机辅助设计中,C0连续性(也称为位置连续性)是指两个曲线或曲面在它们的公共边界上具有相同的位置。这意味着它们在边界处没有缝隙或重叠,但它们的切线方向可以不同。C0连续性是最低级…

独家|京东调整职级序列体系

原有的M、P、T、S主序列将正式合并为新的专业主序列P。 作者|文昌龙 编辑|杨舟 据「市象」独家获悉,京东已在近日在内部宣布对职级序列体系进行调整,将原有的M、P、T、S主序列正式合并为新的专业主序列P,合并后的职级体系将沿用原有专业序…

Echarts 绘制地图

一、Apache Echarts 官网地址:https://echarts.apache.org/ npm install echarts --save 二、获取地图的GeoJSON 地址:DataV.GeoAtlas地理小工具系列 左侧是地图,右侧是JSON数据路径,点击你想要生成的地图省市、地级&#xff0…

想入手养宠宠物空气净化器,养宠宠物空气净化器哪个好?

家里有了宠物后,确实多了很多欢乐,但掉落的毛发也多了不少,特别是换毛期,掉毛问题真的很让人头疼!作为养了多年宠物的铲屎官,我真心推荐大家买一台宠物空气净化器,它能大大提升家里的空气质量&a…

ASUS/华硕ROG掌机 2023款 RC71 NR2301原厂win11系统 工厂文件 带ASUS Recovery恢复

华硕工厂文件恢复系统 ,安装结束后带隐藏分区,一键恢复,以及机器所有驱动软件。 系统版本:windows11 原厂系统下载网址:http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意:仅支持以上型号专用…

nginx 升级http 到 http2

同步发布于我的网站 🚀 背景介绍准备工作配置过程遇到的问题及解决方法验证升级总结参考资料 背景介绍 HTTP/2 是 HTTP 协议的最新版本,相比 HTTP/1.1,它带来了多项重要的改进,包括多路复用、头部压缩和服务端推送。这些特性可…

Spark 内存管理机制

Spark 内存管理 堆内内存和堆外内存 作为一个 JVM 进程,Executor 的内存管理建立在 JVM(最小为六十四分之一,最大为四分之一)的内存管理之上,此外spark还引入了堆外内存(不在JVM中的内存),在spark中是指不…

透视投影(Perspective projection)与等距圆柱投影(Equirectangular projection)

一、透视投影 1.方法概述 Perspective projection(透视投影)是一种模拟人眼观察三维空间物体时的视觉效果的投影方法。它通过模拟观察者从一个特定视点观察三维场景的方式来创建二维图像。在透视投影中,远处的物体看起来比近处的物体小&…

uniapp开发微信小程序笔记8-uniapp使用vant框架

前言:其实用uni-app开发微信小程序的首选不应该是vant,因为vant没有专门给uni-app设置专栏,可以看到目前Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 但是vant的优…

Spring Web MVC其他扩展(详解下)

文章目录 Spring MVC其他扩展(下)异常处理异常处理机制声明式异常好处基于注解异常声明异常处理 拦截器拦截器概念拦截器使用拦截器作用位置图解拦截器案例拦截器工作原理源码 参数校验校验概述操作演示SpringMVC自定义参数验证ValueObject(VO) 文件上传…

【线上问题记录 | 排查网络连接问题】

问题描述 现在有我们程序是部署在服务器A的,A链接的是B。程序从B的redis进行存储和取数据的。 我们的业务是: 信息展示,也就是如果发现机器有异常了,实时进行监控。突然发现有一天,信息显示延迟了。 然后我们就开始排查究竟什么原…

如何保护LabVIEW程序免遭反编译

在正常情况下,LabVIEW程序(即编译后的可执行文件或运行时文件,如 .exe 或 .llb)无法直接被反编译出源码。然而,有一些需要特别注意的点: 1. LabVIEW的编译机制 LabVIEW编译器会将源码(.vi文件&a…

求助:selenium.common.exceptions.SessionNotCreatedException: x x x

1.背景 想要使用python代码接管已打开的浏览器,减少重复登录或者selenium用例执行前的又臭又长的流程 2.报错截图 3.场景 目前是已开启浏览器调试模式且终端未关闭,执行上图中的代码后没有自动输入url且报错 4. 分析 我尝试了add_experimental_optio…

40分钟学 Go 语言高并发:【实战课程】工作池(Worker Pool)实现

工作池(Worker Pool)实战实现 一、知识要点概述 模块核心功能实现难点重要程度池化设计管理协程生命周期并发安全、资源控制⭐⭐⭐⭐⭐动态扩缩容根据负载调整池大小平滑扩缩、性能优化⭐⭐⭐⭐任务分发合理分配任务到worker负载均衡、任务优先级⭐⭐⭐…

Could not locate device support files.

报错信息:Failure Reason: The device may be running a version of iOS (13.6.1 17G80) that is not supported by this version of Xcode.[missing string: 869a8e318f07f3e2f42e11d435502286094f76de] 问题:xcode15升级到xcode16之后,13.…

Ubantu系统docker运行成功拉取失败【成功解决】

解决docker运行成功拉取失败 失败报错 skysky-Legion-Y7000-IRX9:~$ docker run hello-world docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head “http://%2Fvar%2Frun%2Fdocker.sock/_ping”: dial uni…

git rebase-优雅合并与修改提交

文章目录 简介rebase用于合并使用rebase修改提交cherry-pick 简介 在Git核心概念图例与最常用内容操作(reset、diff、restore、stash、reflog、cherry-pick)中我们已经介绍了git的最常用实用的命令。 在上面说的那篇文章中,我们只是简单提了一下rebase。 是因为r…

TongRDS分布式内存数据缓存中间件

命令 优势 支持高达10亿级的数据缓冲,内存优化管理,避免GC性能劣化。 高并发系统设计,可充分利用多CPU资源实现并行处理。 数据采用key-value多索引方式存储,字段类型和长度可配置。 支持多台服务并行运行,服务之间可互…

【大数据学习 | Spark调优篇】Spark之内存调优

1. 内存的花费 1)每个Java对象,都有一个对象头,会占用16个字节,主要是包括了一些对象的元信息,比如指向它的类的指针。如果一个对象本身很小,比如就包括了一个int类型的field,那么它的对象头实…