Spring Boot中@Async注解的使用及原理 + 常见问题及解决方案

07-14 1548阅读

Spring Boot中@Async注解的使用及原理 + 常见问题及解决方案

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~

🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志

🎐 个人CSND主页——Micro麦可乐的博客

🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战

🌺《RabbitMQ》专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战

🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解

💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程

🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整

如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

Spring Boot中@Async注解的使用以及注意事项

  • 1、前言
  • 2、@Async注解的基本使用
    • ❶ 引入依赖
    • ❷ 启用异步支持
    • ❸ 定义异步方法
    • ❹ 调用异步方法
    • 3、@Async注解的实现原理
      • ❶ TaskExecutor
      • ❷ AOP代理
      • ❸ 异步方法返回值
      • 4、应用场景
        • ❶ 后台任务处理
        • ❷ 并行处理
        • ❸ 提高系统吞吐量
        • 5、常见问题及解决方案
          • 5.1、@Async方法调用无效
          • 5.2、异常处理
          • 6、结语

            1、前言

            在现代Java应用程序中,异步处理是提高性能和响应速度的重要手段之一,比如博主之前分享的【Spring Boot 使用自定义注解和自定义线程池实现异步日志记录】,就是采用了异步处理来实现日志记录,而在Spring Boot中它提供了@Async注解来简化异步编程,今天博主就来和小伙伴们分享本@Async注解的基本使用、实现原理以及应用场景。


            2、@Async注解的基本使用

            @Async注解用于标注方法,使其在独立的线程中异步执行。Spring Boot提供了一种简单的方法来启用异步方法调用,只需在配置类或主类上添加@EnableAsync注解

            ❶ 引入依赖

            在 Spring Boot 项目 pom.xml 文件中添加必要的依赖:

                org.springframework.boot
                spring-boot-starter-web
            
            
                org.springframework.boot
                spring-boot-starter-aop
            
            

            ❷ 启用异步支持

            在Spring Boot应用的配置类或主类上启用异步支持 @EnableAsync:

            import org.springframework.boot.SpringApplication;
            import org.springframework.boot.autoconfigure.SpringBootApplication;
            import org.springframework.scheduling.annotation.EnableAsync;
            @SpringBootApplication
            @EnableAsync
            public class AsyncApplication {
                public static void main(String[] args) {
                    SpringApplication.run(AsyncApplication.class, args);
                }
            }
            

            ❸ 定义异步方法

            使用@Async注解定义异步方法。例如:创建一个服务类AsyncService

            import org.springframework.scheduling.annotation.Async;
            import org.springframework.stereotype.Service;
            @Service
            public class AsyncService {
                @Async
                public void asyncMethod() {
                    try {
                        Thread.sleep(5000); // 模拟耗时操作
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("异步方法执行完成");
                }
            }
            

            ❹ 调用异步方法

            在需要调用异步方法的地方,通过注入AsyncService并调用其异步方法

            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RestController;
            @RestController
            @RequestMapping("/api")
            public class AsyncController {
                @Autowired
                private AsyncService asyncService;
                @GetMapping("/async")
                public String callAsyncMethod() {
                    asyncService.asyncMethod();
                    return "异步方法已调用";
                }
            }
            

            最后请求访问Controller/api/async , 会发现Controller立即返回响应,而asyncMethod将在独立线程中执行,5秒后控制台输出:异步方法执行完成


            3、@Async注解的实现原理

            @Async注解的实现依赖于Spring的AOP(面向切面编程)和TaskExecutor

            ❶ TaskExecutor

            Spring 使用TaskExecutor来处理异步任务。默认情况下,Spring Boot使用SimpleAsyncTaskExecutor,但我们也可以自定义TaskExecutor来控制线程池

            自定义TaskExecutor

            我们可以通过@Bean注解定义自定义的TaskExecutor

            import org.springframework.context.annotation.Bean;
            import org.springframework.context.annotation.Configuration;
            import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
            import java.util.concurrent.Executor;
            @Configuration
            public class AsyncConfig {
                @Bean(name = "taskExecutor")
                public Executor taskExecutor() {
                    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
                    executor.setCorePoolSize(5);
                    executor.setMaxPoolSize(10);
                    executor.setQueueCapacity(25);
                    executor.setThreadNamePrefix("AsyncThread-");
                    executor.initialize();
                    return executor;
                }
            }
            

            ❷ AOP代理

            @Async注解通过Spring AOP代理来实现异步调用。当标注为@Async的方法被调用时,Spring AOP会拦截调用并在TaskExecutor的线程池中异步执行该方法

            ❸ 异步方法返回值

            @Async注解的方法可以返回void、Future、CompletableFuture等类型,如下代码

            import org.springframework.scheduling.annotation.Async;
            import org.springframework.stereotype.Service;
            import java.util.concurrent.CompletableFuture;
            @Service
            public class AsyncService {
                @Async
                public CompletableFuture asyncMethodWithReturn() {
                    try {
                        Thread.sleep(5000); // 模拟耗时操作
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return CompletableFuture.completedFuture("异步方法返回结果");
                }
            }
            

            调用带返回值的异步方法:

            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RestController;
            import java.util.concurrent.CompletableFuture;
            @RestController
            public class AsyncController {
                @Autowired
                private AsyncService asyncService;
                @GetMapping("/asyncWithReturn")
                public CompletableFuture callAsyncMethodWithReturn() {
                    return asyncService.asyncMethodWithReturn();
                }
            }
            

            4、应用场景

            @Async注解适用于各种需要异步处理的场景,例如:

            ❶ 后台任务处理

            在Web应用中,有些任务(如发送邮件、生成报告)耗时较长,可以使用@Async异步处理,使用户无需等待任务完成即可获得响应。

            ❷ 并行处理

            对于可以并行处理的任务,如并行数据处理、并行调用多个外部服务,使用@Async可以提高效率。

            ❸ 提高系统吞吐量

            通过异步调用,可以充分利用多线程资源,提高系统的吞吐量和响应速度。


            5、常见问题及解决方案

            5.1、@Async方法调用无效

            如果在同一个类中调用@Async注解的方法,异步调用可能无效。这是因为Spring AOP代理无法拦截同一类中的@Async。

            解决方法:将异步方法放到另一个类中,通过依赖注入进行调用

            5.2、异常处理

            异步方法中的异常不会自动传播到调用方。可以使用CompletableFuture处理异常,见下面演示代码

            import org.springframework.scheduling.annotation.Async;
            import org.springframework.stereotype.Service;
            import java.util.concurrent.CompletableFuture;
            @Service
            public class AsyncService {
                @Async
                public CompletableFuture asyncMethodWithException() {
                    try {
                        Thread.sleep(5000); // 模拟耗时操作
                        throw new RuntimeException("异常发生");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return CompletableFuture.completedFuture("异步方法完成");
                }
            }
            

            处理异常:

            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RestController;
            import java.util.concurrent.CompletableFuture;
            @RestController
            public class AsyncController {
                @Autowired
                private AsyncService asyncService;
                @GetMapping("/asyncWithException")
                public CompletableFuture callAsyncMethodWithException() {
                    return asyncService.asyncMethodWithException()
                            .exceptionally(ex -> "处理异常:" + ex.getMessage());
                }
            }
            

            6、结语

            Spring Boot的@Async注解提供了一种简洁且强大的方式来实现异步处理。通过启用异步支持、定义异步方法并自定义TaskExecutor,可以高效地处理各种异步任务。掌握@Async注解的使用和原理,有助于提升应用程序的性能和响应速度。

            如果本文对您有所帮助,希望 一键三连 给博主一点点鼓励,如果您有任何疑问或建议,请随时留言讨论!


            Spring Boot中@Async注解的使用及原理 + 常见问题及解决方案

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]