SpringBoot异步使用@Async原理及线程池配置

kenx 2021-09-15 07:11:46
SpringBoot 原理 使用 异步 async


前言

在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢

使用步骤

完成异步操作一般有两种,消息队列MQ,和线程池处理ThreadPoolExecutor

而在Spring4中提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用@Async,这个注解让我们在使用Spring完成异步操作变得非常方便

配置线程池类参数配置

自定义常量类

public class ConstantFiledUtil { public static final String AUTHORIZATION_TOKEN = "authorizationToken"; /** * kmall线程池名称 */ public static final String KMALL_THREAD_POOL = "KmallThreadPool"; /** * kmall线程名称前缀 */ public static final String KMALL_THREAD_NAME_PREFIX = "kmall-thread-";}

配置线程池

@Configuration(proxyBeanMethods = false)@EnableAsync //开启注解public class KmallConfig { @Bean(ConstantFiledUtil.KMALL_THREAD_POOL) public ThreadPoolTaskExecutor FebsShiroThreadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //配置核心线程数 executor.setCorePoolSize(5); //配置最大线程数 executor.setMaxPoolSize(20); //配置队列大小 executor.setQueueCapacity(200); //线程池维护线程所允许的空闲时间 executor.setKeepAliveSeconds(30); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix(ConstantFiledUtil.KMALL_THREAD_NAME_PREFIX); //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); //设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住 executor.setAwaitTerminationSeconds(60); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; }}

注意这里需要通过@EnableAsync开启异步否则无效

自定义线程任务

public interface ILogService extends IService<Log> { /** * 分页搜索查询日志信息 * @param logParams * @return */ IPage getSearchLogByPage(SearchLogParams logParams); /** * 保存日志 * * @param logSubject */ @Async void saveLog(LogSubject logSubject);}

在需要异步执行的接口,或者方法上加上@Async注解此方法就是异步方法,在主程序中调用的化,就是异步方式单独线程执行

此注解表明saveLog方法进入的线程池是KmallThreadPool方法创建的。

我们也可以单独指定方法名称@Async("saveLogs")

这样在进行日记记录的时候就是单独线程执行每次请求都快速响应了,而耗时的操作都留给线程池中的线程去异步执行

总结

Spring中用@Async注解标记的方法,称为异步方法。在spring boot应用中使用@Async很简单:

  1. 调用异步方法类上或者启动类加上注解@EnableAsync
  2. 在需要被异步调用的方法外加上@Async
  3. 所使用的@Async注解方法的类对象应该是Spring容器管理的bean对象;

注意同一个类里面调用异步方法不生效:原因默认类内的方法调用不会被aop拦截,即调用方和被调用方是在同一个类中,是无法产生切面的,该对象没有被Spring容器管理。即@Async方法不生效

解决办法:

如果要使同一个类中的方法之间调用也被拦截,需要使用spring容器中的实例对象,而不是使用默认的this,因为通过bean实例的调用才会被spring的aop拦截本例使用方法:AsyncService asyncService = context.getBean(AsyncService.class); 然后使用这个引用调用本地的方法即可达到被拦截的目的备注:这种方法只能拦截protected,default,public方法,private方法无法拦截。这个是spring aop的一个机制。

原理刨析

异步方法返回类型只能有两种:

  1. 当返回类型为void的时候,方法调用过程产生的异常不会抛到调用者层面,可以通过注AsyncUncaughtExceptionHandler来捕获此类异常

  2. 当返回类型为Future的时候,方法调用过程产生的异常会抛到调用者层面

注意如果不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutorSimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。并发大的时候会产生严重的性能问题

Spring异步线程池接口 TaskExecutor

看源码可知

@FunctionalInterfacepublic interface TaskExecutor extends Executor { void execute(Runnable var1);}

它的实先类有很多如下:

SpringBoot异步使用@Async原理及线程池配置

  1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。

  2. SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方

  3. ConcurrentTaskExecutor:Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类

  4. SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类

  5. ThreadPoolTaskExecutor :最常使用,推荐。 其实质是对java.util.concurrent.ThreadPoolExecutor的包装,————————————————

文章参考

  1. Spring Boot(5) @Async异步线程池详解
  2. https://segmentfault.com/a/1190000040134160?utm_source=sf-similar-article
版权声明
本文为[kenx]所创,转载请带上原文链接,感谢
https://www.helloworld.net/p/8728882706

  1. Opérateurs arithmétiques et opérateurs de comparaison pour JavaScript, Introduction classique au développement web
  2. MySQL + +: slow query log analysis (I)
  3. Explorer le cadre open source Android - 1. Okhttp Source Analysis
  4. 分布式宝典:限流 缓存 通讯,Java开发中常见的一些问题面试专题,
  5. 分享面试经历的网站,腾讯大牛教你自己写Java框架!
  6. Expliquer les six principes de base du modèle de conception par des exemples réels
  7. Site Web pour partager vos expériences d'entrevue, Tencent Bull vous apprend à écrire votre propre cadre Java!
  8. Dictionnaire distribué: communication de cache limitée par le courant, sujets d'entrevue pour certaines questions courantes dans le développement Java,
  9. Another uncle circle man is angry! The high-quality acting skills make people admire and achieve the highlight of the ending of spring in Jade House
  10. 10. MySQL database import, export and authorization
  11. 9. MySQL data query
  12. 8. MySQL data operation DML
  13. 7. MySQL database table engine and character set
  14. 分享面試經曆的網站,騰訊大牛教你自己寫Java框架!
  15. Les points de connaissance de Java Real - time Video Download, Byte Jumping Java R & D post ont été divulgués à l'intérieur.
  16. Introduction au JavaScript chapitre 15 (objets, clairvoyance)
  17. 前方高能,Java程序员最大的悲哀是什么?
  18. 别再说你不会JVM性能监控和调优了,2021华为Java高级面试题及答案,
  19. Tencent private cloud MySQL solution tdsql
  20. 前方高能,Java程序員最大的悲哀是什麼?
  21. Quelle est la plus grande tristesse des programmeurs Java à l'avenir?
  22. 15 useful cron work examples commonly used by Senior Linux system administrators
  23. Ne dites pas que vous ne pouvez pas surveiller et ajuster les performances JVM, 2021 Huawei Java Advanced interview Questions and Answers,
  24. 別再說你不會JVM性能監控和調優了,2021華為Java高級面試題及答案,
  25. 十多家大厂Java面试真题锦集干货整理,Java开发者该学习哪些东西提高竞争力?
  26. 十分钟带你回顾Spring常问的知识点,35岁老年程序员的绝地翻身之路,
  27. 区区一个SpringBoot问题就被干趴下了,看完这一篇就够了!
  28. K8s gestion des ressources (opérations de base)
  29. Java and cloud native dating
  30. 區區一個SpringBoot問題就被幹趴下了,看完這一篇就够了!
  31. Un problème de démarrage de printemps dans le district a été séché, et c'est assez!
  32. Dix minutes pour vous faire passer en revue les points de connaissance que Spring demande souvent, le chemin du retour Jedi d'un programmeur âgé de 35 ans,
  33. Plus d'une douzaine de grandes usines Java interview vrai sujet brocade collection de marchandises sèches, les développeurs Java devraient apprendre ce qui améliore la compétitivité?
  34. 十分鐘帶你回顧Spring常問的知識點,35歲老年程序員的絕地翻身之路,
  35. Guide de route d'apprentissage Java, redis a plusieurs types de données?
  36. 华为Java高级工程师面试题,字节跳动上千道精选面试题还不刷起来!
  37. 华为Java面试题目,腾讯Java开发面试记录,
  38. Propriétés et méthodes des objets Array en javascript!,Pseudo - classes et pseudo - éléments pour CSS
  39. Design pattern -- agent pattern
  40. 華為Java面試題目,騰訊Java開發面試記錄,
  41. Huawei Java interview title, Tencent Java Development interview record,
  42. Huawei Java Senior Engineer interview question, Byte Jumping thousand Selected Interview Question is still not Brushed!
  43. 双非本科字节跳动Java面试题分享,一篇文章教你搞定计算机网络面试,
  44. 又到一年金三银四,2021最新Java笔试题及答案,
  45. Huawei Finance and Economics 2021 Spring Recruitment interview, what is distributed Lock?Pourquoi utiliser des serrures distribuées?
  46. Un an plus tard, Golden, Silver, Silver, and Silver, 2021, the latest Java written Examination Questions and Answers,
  47. Partage de questions d'entrevue Java à double saut d'octets non - premier cycle, un article vous apprend à gérer l'entrevue réseau informatique,
  48. Computer graduation project java online voting system based on SSM
  49. K8s gestion des ressources (opérations de base)
  50. 又到一年金三銀四,2021最新Java筆試題及答案,
  51. Collection de code de base JavaScript (1)
  52. Vérification des permissions d'interface pour le démarrage du printemps à l'aide d'annotations personnalisées AOP +.
  53. Vérification des permissions d'interface pour le démarrage du printemps à l'aide d'annotations personnalisées AOP +.
  54. Cloud Security Daily 210914: Red Hat Jboss Middleware Platform found important Security Vulnerability and needs to be upgraded as soon as possible
  55. 吐血整理,腾讯团队实力打造spring入门教程,
  56. 史上最全的微服务专业术语面试50问,字节跳动Java岗经典面试真题,
  57. Absolument!C'est l'analyse la plus détaillée du code source de hashtap que j'ai jamais vu!
  58. Computer graduation project Java logistics order management system of logistics company based on SSM
  59. Talk about Kafka: source code analysis of producer
  60. [springboot2 starts from 0] development tips - Lombok, devtools, spring initailizr