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

kenx 2021-09-15 07:13:23
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://javamana.com/2021/09/20210915071141180Z.html

  1. 别再说你不会JVM性能监控和调优了,2021华为Java高级面试题及答案,
  2. 15 useful cron work examples commonly used by Senior Linux system administrators
  3. Ne dites pas que vous ne pouvez pas surveiller et ajuster les performances JVM, 2021 Huawei Java Advanced interview Questions and Answers,
  4. 別再說你不會JVM性能監控和調優了,2021華為Java高級面試題及答案,
  5. 十多家大厂Java面试真题锦集干货整理,Java开发者该学习哪些东西提高竞争力?
  6. 十分钟带你回顾Spring常问的知识点,35岁老年程序员的绝地翻身之路,
  7. 区区一个SpringBoot问题就被干趴下了,看完这一篇就够了!
  8. K8s gestion des ressources (opérations de base)
  9. Java and cloud native dating
  10. 區區一個SpringBoot問題就被幹趴下了,看完這一篇就够了!
  11. Un problème de démarrage de printemps dans le district a été séché, et c'est assez!
  12. 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,
  13. 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é?
  14. 十分鐘帶你回顧Spring常問的知識點,35歲老年程序員的絕地翻身之路,
  15. Guide de route d'apprentissage Java, redis a plusieurs types de données?
  16. 华为Java高级工程师面试题,字节跳动上千道精选面试题还不刷起来!
  17. 华为Java面试题目,腾讯Java开发面试记录,
  18. Propriétés et méthodes des objets Array en javascript!,Pseudo - classes et pseudo - éléments pour CSS
  19. Design pattern -- agent pattern
  20. 華為Java面試題目,騰訊Java開發面試記錄,
  21. Huawei Java interview title, Tencent Java Development interview record,
  22. Huawei Java Senior Engineer interview question, Byte Jumping thousand Selected Interview Question is still not Brushed!
  23. 双非本科字节跳动Java面试题分享,一篇文章教你搞定计算机网络面试,
  24. 又到一年金三银四,2021最新Java笔试题及答案,
  25. Huawei Finance and Economics 2021 Spring Recruitment interview, what is distributed Lock?Pourquoi utiliser des serrures distribuées?
  26. Un an plus tard, Golden, Silver, Silver, and Silver, 2021, the latest Java written Examination Questions and Answers,
  27. Partage de questions d'entrevue Java à double saut d'octets non - premier cycle, un article vous apprend à gérer l'entrevue réseau informatique,
  28. Computer graduation project java online voting system based on SSM
  29. K8s gestion des ressources (opérations de base)
  30. 又到一年金三銀四,2021最新Java筆試題及答案,
  31. Collection de code de base JavaScript (1)
  32. Vérification des permissions d'interface pour le démarrage du printemps à l'aide d'annotations personnalisées AOP +.
  33. Vérification des permissions d'interface pour le démarrage du printemps à l'aide d'annotations personnalisées AOP +.
  34. Cloud Security Daily 210914: Red Hat Jboss Middleware Platform found important Security Vulnerability and needs to be upgraded as soon as possible
  35. 吐血整理,腾讯团队实力打造spring入门教程,
  36. 史上最全的微服务专业术语面试50问,字节跳动Java岗经典面试真题,
  37. Absolument!C'est l'analyse la plus détaillée du code source de hashtap que j'ai jamais vu!
  38. Computer graduation project Java logistics order management system of logistics company based on SSM
  39. Talk about Kafka: source code analysis of producer
  40. [springboot2 starts from 0] development tips - Lombok, devtools, spring initailizr
  41. 国内一线互联网公司面试题汇总,2021年大厂Java岗面试必问,
  42. 啃完吃透保你涨薪5K,熬夜整理小米Java面试题,
  43. 和字节跳动大佬的技术面谈,Redis成神之路电子版教程已问世,
  44. Le terme professionnel le plus complet de l'histoire des micro - services interview 50 questions, Byte Jumping Java post Classic interview vrai problème,
  45. After using mybatisplus, I haven't written SQL for a long time
  46. [springboot2 starts from 0] how to write a springboot application?
  47. Huawei cloud guassdb (for redis) released a new version, and the two core features were officially unveiled
  48. 和字節跳動大佬的技術面談,Redis成神之路電子版教程已問世,
  49. 啃完吃透保你漲薪5K,熬夜整理小米Java面試題,
  50. Avec l'interview technique du gigolo, le tutoriel électronique redis est sorti.
  51. Après avoir mangé, assurez - vous d'augmenter votre salaire de 5K et de rester debout tard pour trier les questions d'entrevue Java de millet.
  52. Résumé des questions d'entrevue pour les entreprises Internet nationales de première ligne, qui doivent être posées lors de l'entrevue d'emploi Java de la grande usine en 2021,
  53. Le tri des crachats de sang, la force de l'équipe Tencent pour créer le tutoriel d'introduction au printemps,
  54. Java and scala concurrency Fundamentals
  55. Analysis of java thread source code based on Hotspot
  56. 國內一線互聯網公司面試題匯總,2021年大廠Java崗面試必問,
  57. Introduction au module de contrôle de Connexion MySQL
  58. 大厂高级测试面试题,Java面试基础技能罗列,
  59. Comprendre l'architecture sous - jacente d'InnoDB en exécutant une instruction
  60. Chargeur de classe 1 Tomcat