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

news2024/11/26 7:18:22

文章目录

  • 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注解

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

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

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

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

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

相关文章

WebGIS技术汇总

WebGIS系统通常都围绕地图进行内容表达,但并不是有地图就一定是WebGIS,所以有必要讨论下基于Web的地图API分类及应用场景。 Web上的Map API主要分类如下几类: Charts:以D3.js,Echarts等为代表。LBS:以高德…

使用Vue3来实现一个倒计时器以及倒计时任务

本内容使用Vue3,以及element-plus辅助开发。 首先展示倒计时器的功能: 手动设置倒计时器的倒计时时间开始倒计时按钮暂停倒计时按钮重新开始倒计时按钮 其次展示倒计时任务管理界面功能: 创建倒计时任务选择任务并进行倒计时删除任务 目录 一…

VMware Workstation 虚拟机运行卡顿解决方案

前言 由于我们网站主力是模拟器多开,VMware虚拟机纯属我个人使用的经验,仅供参考。顺带一提:多开鸭的系统精简掉的是Hyper-V,跟VMware完全没有任何关系,Hyper-V跟雷电这些模拟器会冲突,但是移除之后不会影…

GitLab|应用部署

创建docker-compose.yaml文件 输入docker-compose配置 version: 3.8 services:gitlab:image: gitlab/gitlab-ce:15.11.2-ce.0restart: alwayscontainer_name: gitlab-ceprivileged: truehostname: 192.168.44.235environment:TZ: Asia/ShanghaiGITLAB_OMNIBUS_CONFIG: |exter…

ssm182在线作业管理系统的设计与实现+vue(论文+源码)_kaic

设计题目:在线作业管理系统的设计与实现 摘 要 网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所…

LeetCode-632. Smallest Range Covering Elements from K Lists [C++][Java]

目录 题目描述 解题思路 【C】 【Java】 LeetCode-632. Smallest Range Covering Elements from K Listshttps://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/description/ 题目描述 You have k lists of sorted integers in non-decreasing o…

指针的奥秘:深入探索内存的秘密

前言 在计算机编程的广阔天地中,指针作为一种独特的数据类型,它不仅是C语言的核心,也是理解计算机内存管理的基石。指针的概念虽然强大,但对于初学者来说,它常常是学习过程中的一个难点。本文旨在揭开指针的神秘面纱&a…

⭐ Unity 资源管理解决方案:Addressable_ Demo演示

一、使用Addressable插件的好处: 1.自动管理依赖关系 2.方便资源卸载 3.自带整合好的资源管理界面 4.支持远程资源加载和热更新 二、使用步骤 安装组件 1.创建资源分组 2.将资源加入资源组 3.打包资源 4.加载资源 三种方式可以加载 using System.Collections…

红日靶场-4

环境搭建 我们这里会拿到三台主机,一台web主机,一台win7主机,一台DC主机 机器密码 WEB主机 ubuntu:ubuntu WIN7主机 douser:Dotest123 (DC)WIN2008主机 administrator:Test2008 登陆后需修改密码,我这里修改为1qazWSX 网络配…

使用八爪鱼爬虫抓取汽车网站数据,分析舆情数据

我是做汽车行业的,可以用八爪鱼爬虫抓取汽车之家和微博上的汽车文章内容,分析各种电动汽车口碑数据。 之前,我写过很多Python网络爬虫的案例,使用requests、selenium等技术采集数据,这次尝试去采集小米SU7在微博、汽车…

具有多个表盘、心率传感器、指南针和游戏的 DIY 智能手表

在此,我们将使用所学到的知识,结合使用硬件和软件组件从头开始创建自己的智能手表。在项目的这一部分,您将被指导完成组装硬件组件、设置软件以及配置智能手表的设置和功能的过程。到本项目结束时,您将拥有一款功能齐全的智能手表…

Django+Nginx+uwsgi网站Channels+redis+daphne多人在线聊天实现粘贴上传图片

在DjangoNginxuwsgi网站Channelsredisdaphne多人在线的基础上(详见DjangoNginxuwsgi网站使用Channelsredisdaphne实现简单的多人在线聊天及消息存储功能-CSDN博客),实现在输入框粘贴或打开本地图片,上传到网站后返回图片路径&…

[ubuntu]编译共享内存读取出现read.c:(.text+0x1a): undefined reference to `shm_open‘问题解决方案

问题log /tmp/ccByifPx.o: In function main: read.c:(.text0x1a): undefined reference to shm_open read.c:(.text0xd9): undefined reference to shm_unlink collect2: error: ld returned 1 exit status 程序代码 #include <stdio.h> #include <stdlib.h> #…

Otter 安装流程

优质博文&#xff1a;IT-BLOG-CN 一、背景 随着公司的发展&#xff0c;订单库的数据目前已达到千万级别&#xff0c;需要进行分表分库&#xff0c;就需要对数据进行迁移&#xff0c;我们使用了otter&#xff0c;这里简单整理下&#xff0c;otter 的安装过程&#xff0c;希望对…

wsl2的Ubuntu18.04安装ros和anaconda

参考&#xff1a;超详细 WSL2 安装 ros 和 anaconda_wsl2安装anaconda-CSDN博客 一.安装ros 1. 更换系统源 输入 wget http://fishros.com/install -O fishros && . fishros 和上面的链接一样&#xff0c;依次输入5-2-1 2. 安装ros 输入 wget http://fishros.c…

鸿蒙NEXT开发案例:字数统计

【引言】 本文将通过一个具体的案例——“字数统计”组件&#xff0c;来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量&#xff0c;还具有良好的用户界面设计&#xff0c;使用户能够直观地了解输入文本…

【经典】抽奖系统(HTML,CSS、JS)

目录 1、添加参与者 2、多次添加 3、点击抽奖 功能介绍&#xff1a; 使用方法&#xff1a; 完整代码&#xff1a; 一个简单但功能强大的抽奖系统的示例&#xff0c;用于在网页上实现抽奖。 1、添加参与者 2、多次添加 3、点击抽奖 功能介绍&#xff1a; 参与者添加&…

用树莓派Pico控制8×8 LED点阵屏:深入解析C++核心知识与动态显示实现

88 LED点阵屏是一种直观的硬件显示工具,广泛应用于嵌入式开发中。本项目结合树莓派Pico和HT16K33驱动芯片,通过C++编程实现动态图案和文字的显示功能。本文将全面解析项目中的C++核心知识点,帮助读者深入理解C++在硬件编程中的实际应用。 一、项目背景与硬件简介 1. 项目目…

什么是 WPF 中的依赖属性?有什么作用?

依赖属性&#xff08;Dependency Property&#xff09;是 WPF 的一个核心概念&#xff0c;它为传统的 .NET 属性提供了增强功能&#xff0c;支持绑定、样式、动画和默认值等功能。通过依赖属性&#xff0c;WPF 提供了一种灵活的数据驱动的方式来处理 UI 属性。 1. 什么是依赖属…

视频分析设备平台EasyCVR视频设备轨迹回放平台与应急布控球的视频监控方案

在现代社会&#xff0c;随着城市化进程的加快和信息技术的不断进步&#xff0c;对于公共安全、交通管理、城市管理以及环境保护等领域的监控需求日益增长。应急布控球与EasyCVR视频监控方案的结合&#xff0c;正是为了满足这些领域对实时监控和快速响应的需求。这一组合利用最新…