• SpringBoot中异步注解@Async介绍


    介绍在SpringBoot项目中,使用@Async不生效的原因介绍和分析;

    代码参考gitee仓库:spring-boot-2022-05: 主要是介绍Spring框架注解、常用的功能的使用案例,记录平时遇到的技术知识点,进行实践操作; - Gitee.com

     一、常见原因:

    1.启动类中没有添加注解@EnableAsync;

    2.同一个类中调用含有@Async的方法;因为@Transactional和@Async是采用Spring AOP原理实现的,需要通过代理对象调用其方法。

    3.方法必须是public修饰,且返回值是void或Future。

    4.使用ThreadPoolTaskExecutor对象创建自定义线程池?

    5.关于@Async("param")中参数param含义?

    正确使用步骤事项:

    第一步:启动类中应该添加注解@EnableAsync;

    第二步:执行方法和异步方法不在同一个类中。

    第三步:异步方法必须是public 修饰,且返回值是void或Future;

    二、具体案例:

    1.启动类需要添加注解@EnableAsync

    1. package com.dbzhang;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.scheduling.annotation.EnableAsync;
    5. /**
    6. * @program: spring-boot-2022-05
    7. * @description:
    8. * @author: zdb
    9. * @motto: 认真写好每一行代码
    10. * @create: 2022-05-05 13:15
    11. */
    12. @SpringBootApplication
    13. @EnableAsync
    14. public class ApplicationRun {
    15. public static void main(String[] args) {
    16. SpringApplication.run(ApplicationRun.class, args);
    17. }
    18. }

    2.PlayerService业务类:通过代理对象调用异步方法发送短信asyncMethodClass.sendMessage(playerId, msg);

    1. package com.dbzhang.asyc;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.stereotype.Component;
    4. import javax.annotation.Resource;
    5. /**
    6. * @program: spring-boot-2022-05
    7. * @description:
    8. * @author: zdb
    9. * @motto: 认真写好每一行代码
    10. * @create: 2022-10-18 13:11
    11. */
    12. @Component
    13. @Slf4j
    14. public class PlayerService {
    15. @Resource
    16. private AsyncMethodClass asyncMethodClass;
    17. public void register(Long playerId) {
    18. log.info("begin----注册用户编号,playerId:{}", playerId);
    19. //异步发送短信
    20. String msg = "异步发送短信";
    21. asyncMethodClass.sendMessage(playerId, msg);
    22. log.info("end----注册用户编号,playerId:{}", playerId);
    23. }
    24. }

    3.AsyncMethodClass中异步方法,使用@Async("param")标记异步方法,其中param参数是引用线程池的bean名称,但是Spring容器中必须存在这个bean。

    1. package com.dbzhang.asyc;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.scheduling.annotation.Async;
    4. import org.springframework.stereotype.Component;
    5. /**
    6. * @program: spring-boot-2022-05
    7. * @description:
    8. * @author: zdb
    9. * @motto: 认真写好每一行代码
    10. * @create: 2022-10-18 13:12
    11. */
    12. @Component
    13. @Slf4j
    14. public class AsyncMethodClass {
    15. /**
    16. * 测试调用异常方法:发送短信
    17. *
    18. */
    19. @Async("threadPoolTaskExecutor")
    20. public void sendMessage(Long playerId, String msg) {
    21. log.info("玩家注册编号playerId:{},发送短信信息msg:{}", playerId, msg);
    22. }
    23. }

    4.自定义线程池ThreadPoolTaskExector,并交给Spring容器管理。

    1. package com.dbzhang.asyc;
    2. import org.springframework.beans.factory.annotation.Value;
    3. import org.springframework.context.annotation.Bean;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    6. /**
    7. * @program: spring-boot-2022-05
    8. * @description: 自定义线程池配置
    9. * @author: zdb
    10. * @motto: 认真写好每一行代码
    11. * @create: 2022-10-19 12:50
    12. */
    13. @Configuration
    14. public class AsyncThreadParam {
    15. @Value("${threadPool.corePoolSize}")
    16. private int corePoolSize;
    17. @Value("${threadPool.maxPoolSize}")
    18. private int maxPoolSize;
    19. @Value("${threadPool.keepAliveSeconds}")
    20. private int keepAliveSeconds;
    21. @Value("${threadPool.queueCapacity}")
    22. private int queueCapacity;
    23. @Value("${threadPool.namePrefix}")
    24. private String namePrefix;
    25. /**
    26. * 初始化线程池参数
    27. *
    28. * @return
    29. */
    30. @Bean(value = "threadPoolTaskExecutor")
    31. public ThreadPoolTaskExecutor initThreadPoolTaskExecutor() {
    32. ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    33. threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
    34. threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
    35. threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
    36. threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
    37. threadPoolTaskExecutor.setThreadNamePrefix(namePrefix);
    38. // threadPoolTaskExecutor.setRejectedExecutionHandler();
    39. return threadPoolTaskExecutor;
    40. }
    41. }

    5.配置文件中执行线程参数:

    1. #自定义线程池ThreadPoolTaskExecutor参数
    2. threadPool:
    3. corePoolSize: 2
    4. maxPoolSize: 5
    5. keepAliveSeconds: 60
    6. queueCapacity: 10
    7. namePrefix: async-zdb-

    6.测试类:

    1. package com.dbzhang.async;
    2. import com.dbzhang.asyc.PlayerService;
    3. import org.junit.Test;
    4. import org.junit.runner.RunWith;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.boot.test.context.SpringBootTest;
    7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    8. /**
    9. * @program: spring-boot-2022-05
    10. * @description:
    11. * @author: zdb
    12. * @motto: 认真写好每一行代码
    13. * @create: 2022-10-18 13:18
    14. */
    15. @RunWith(SpringJUnit4ClassRunner.class)
    16. @SpringBootTest
    17. public class AsyncTest {
    18. @Autowired
    19. private PlayerService playerService;
    20. @Test
    21. public void testAsync() {
    22. playerService.register(123456789L);
    23. }
    24. }

     7.执行结果:

     

  • 相关阅读:
    【测开】Java快转Python 学习路径记录
    Docker | 专栏文章整理🎉🎉
    C++ Map empty()实例讲解
    【英语:基础进阶_核心词汇扩充】E5.常见词根拓词
    Skywalking APM监控系列(二、Mysql、Linux服务器与前端JS接入Skywalking监听)
    【docker专栏8】使用IDEA远程管理docker镜像及容器服务
    Java面向对象编程---基础篇
    音视频过滤器实战--音频混音
    第四章 :Spring Boot 配置文件指南
    KingbaseESV8R6垃圾回收受到参数old_snapshot_threshold的影响
  • 原文地址:https://blog.csdn.net/zdb292034/article/details/127406128