成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺析Spring中Async注解底層異步線程池原理

開發 前端
? Spring創建SimpleAsyncTaskExecutor實例來處理Async注解的異步任務,SimpleAsyncTaskExecutor不是一個好的線程池實現類,SimpleAsyncTaskExecutor根據需要在當前線程或者新線程中執行異步任務。

一、前言

開發中我們經常會用到異步方法調用,具體到代碼層面,異步方法調用的實現方式有很多種,比如最原始的通過實現Runnable接口或者繼承Thread類創建異步線程,然后啟動異步線程;再如,可以直接用java.util.concurrent包提供的線程池相關API實現異步方法調用。

如果說可以用一行代碼快速實現異步方法調用,那是不是比上面方法香很多。

Spring提供了Async注解,就可以幫助我們一行代碼搞定異步方法調用。Async注解用起來是很爽,但是如果不對其底層實現做深入研究,難免有時候也會心生疑慮,甚至會因使用不當,遇見一些讓人摸不著頭腦的問題。

本文首先將對Async注解做簡單介紹,然后和大家分享一個我們項目中因Async注解使用不當的線上問題,接著再深扒Spring源碼,對Async注解底層異步線程池的實現原理一探究竟。

二、Async注解簡介

Async注解定義源碼

圖片圖片

從源碼可以看出@Async注解定義很簡單,只需要關注兩點:

  • Target({ElementType.TYPE, ElementType.METHOD})標志Async注解可以作用在方法和類上,作用在類上時,類的所有方法可以實現異步調用。
  • String value( ) default ""是唯一字段屬性,用來指定異步線程池,且該字段有缺省值。

Async注解異步調用實現原理概述

在Spring框架中,Async注解的實現是通過AOP來實現的。具體來說,Async注解是由AsyncAnnotationAdvisor這個切面類來實現的。

AsyncAnnotationAdvisor類是Spring框架中用于處理Async注解的切面,它會在被Async注解標識的方法被調用時,創建一個異步代理對象來執行方法。這個異步代理對象會在一個新的線程中調用被@Async注解標識的方法,從而實現方法的異步執行。

在AsyncAnnotationAdvisor中,會使用AsyncExecutionInterceptor來處理Async注解。AsyncExecutionInterceptor是實現了MethodInterceptor接口的類,用于攔截被Async注解標識的方法的調用,并在一個新的線程中執行這個方法。

通過AOP的方式實現Async注解的異步執行,Spring框架可以在方法調用時動態地創建代理對象來實現異步執行,而不需要在業務代碼中顯式地創建新線程。

總的來說,Async注解的實現是通過AOP機制來實現的,具體的切面類是AsyncAnnotationAdvisor,它利用AsyncExecutionInterceptor來處理被Async注解標識的方法的調用,實現方法的異步執行。

三、Async注解底層異步線程池原理探究

獲取Async注解線程池主流程解析

進入到Spring源碼Async注解AOP切面實現部分,我們重點剖析異步調用實現中線程池是怎么處理的。下圖是org.springframework.aop.interceptor.AsyncExecutionInterceptor#invoke方法的實現,可以看出是調用determineAsyncExecutor方法獲取異步線程池。

AsyncExecutionInterceptor#invokeAsyncExecutionInterceptor#invoke

下圖是determineAsyncExecutor方法實現:

圖片圖片

圖片圖片

左圖為AsyncExecutionInterceptor#determineAsyncExecutor,右圖為AsyncExecutionAspectSupport#getExecutorQualifier

從代碼實現中可以看到determineAsyncExecutor獲取線程池的大致流程:

determineAsyncExecutor獲取線程池流程determineAsyncExecutor獲取線程池流程

如果在使用Async注解時指定了自定義線程池比較好理解,如果使用Async注解時沒有指定自定義線程池,Spring是怎么處理默認線程池呢?繼續深入源碼看看Spring提供的默認線程池的實現。

Spring是怎么為Async注解提供默認線程池的

Async注解默認線程池有下面兩個方法實現:   

  • org.springframework.aop.interceptor.AsyncExecutionInterceptor#getDefaultExecutor
  • org.springframework.aop.interceptor.AsyncExecutionAspectSupport#getDefaultExecutor

AsyncExecutionInterceptor#getDefaultExecutorAsyncExecutionInterceptor#getDefaultExecutor

可以看出AsyncExecutionInterceptor#getDefaultExecutor方法比較簡單:先嘗試調用父類AsyncExecutionAspectSupport#getDefaultExecutor方法獲取線程池,如果父類方法獲取不到線程池再用創建SimpleAsyncTaskExecutor對象作為Async的線程池返回。

AsyncExecutionAspectSupport#getDefaultExecutorAsyncExecutionAspectSupport#getDefaultExecutor

再來看父類AsyncExecutionAspectSupport#getDefaultExecutor方法的實現,可以看到Spring根據類型從Spring容器中獲取TaskExecutor類的實例,先記住這個關鍵點。

我們知道,Spring根據類型獲取實例時,如果spring容器中有且只有一個指定類型的實例對象,會直接返回,否則的話,會拋出NoUniqueBeanDefinitionException異常或者NoSuchBeanDefinitionException異常。

但是,對于Executor類型,Spring容器卻“網開一面”,有一個特殊處理:當從Spring容器中獲取Executor實例對象時,如果滿足@ConditionalOnMissingBean(Executor.class)條件,Spring容器會自動裝載一個ThreadPoolTaskExecutor實例對象,而ThreadPoolTaskExecutor是TaskExecutor的實現類。

圖片圖片

圖片圖片

左圖為TaskExecutionAutoConfiguration,右圖為TaskExecutionProperties

從TaskExecutionProperties和TaskExecutionAutoConfiguration兩個配置類我們看到Spring自動裝載的ThreadPoolTaskExecutor線程池對象的參數:核心線程數=8;最大線程數=Integer.MAX_VALUE;隊列大小=Integer.MAX_VALUE。

四、總結

現在Async注解線程池源碼已經看的差不多了,下面這張圖是Spring處理Async異步線程池的流程:

Async異步線程池獲取流程Async異步線程池獲取流程

歸納一下:如果在使用Async注解時沒有指定自定義的線程池會出現以下幾種情況:

  • 當Spring容器中有且僅有一個TaskExecutor實例時,Spring會用這個線程池來處理Async注解的異步任務,這可能會踩坑,如果這個TaskExecutor實例是第三方jar引入的,可能會出現很詭異的問題。
  • Spring創建一個核心線程數=8、最大線程數=Integer.MAX_VALUE、隊列大小=Integer.MAX_VALUE的線程池來處理Async注解的異步任務,這時候也可能會踩坑,由于線程池參數設置不合理,核心線程數=8,隊列大小過大,如果有大批量并發任務,可能會出現OOM。
  • Spring創建SimpleAsyncTaskExecutor實例來處理Async注解的異步任務,SimpleAsyncTaskExecutor不是一個好的線程池實現類,SimpleAsyncTaskExecutor根據需要在當前線程或者新線程中執行異步任務。如果當前線程已經有空閑線程可用,任務將在當前線程中執行,否則將創建一個新線程來執行任務。由于這個線程池沒有線程管理的能力,每次提交任務都實時創建新城,所以如果任務量大,會導致性能下降。
責任編輯:武曉燕 來源: 得物技術
相關推薦

2024-12-17 00:00:00

Spring線程

2018-06-21 14:46:03

Spring Boot異步調用

2020-11-05 11:14:29

Docker底層原理

2009-07-22 09:39:18

CLR線程池

2023-02-12 23:23:30

2024-03-28 12:51:00

Spring異步多線程

2024-07-12 14:46:20

2009-08-21 11:31:59

異步和多線程的區別

2022-09-28 14:54:07

Spring注解方式線程池

2024-08-22 10:39:50

@Async注解代理

2025-04-08 00:00:00

@AsyncSpring異步

2024-05-07 08:23:03

Spring@Async配置

2023-07-31 08:05:30

Spring任務調度

2021-11-11 15:25:28

@AsyncJava線程池

2025-06-09 01:01:00

2009-07-09 10:28:19

線程池JDK5

2021-08-04 17:20:30

阿里巴巴AsyncJava

2024-03-06 07:52:21

Spring框架響應式編程微服務架構

2022-11-15 08:10:23

SpringMyBatis底層

2012-05-15 02:18:31

Java線程池
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 四虎成人在线播放 | 天天影视网天天综合色在线播放 | 欧美日韩亚洲在线 | 日韩欧美国产精品综合嫩v 一区中文字幕 | 天天操夜夜操免费视频 | 日本在线视频一区二区 | 国产精品久久久久一区二区三区 | 亚洲精品国产成人 | 97国产爽爽爽久久久 | 中文字幕亚洲一区 | 天天看天天爽 | 国产福利在线播放 | 日本在线综合 | xxxxxx国产 | 亚洲国产福利视频 | 在线日韩av电影 | 成人一级黄色毛片 | 午夜影院在线观看视频 | 国产精品一区二区三区久久久 | 国产成人精品一区二区三区在线 | 欧洲在线视频 | 草久久免费视频 | 一级看片 | 久久国产欧美日韩精品 | 国产一区久久 | 亚洲综合色视频在线观看 | 欧美一区二区三区视频 | 欧美日韩在线观看一区 | 成人午夜免费视频 | 亚洲国产欧美在线 | 亚洲一一在线 | 国产精品伦理一区 | 国产欧美一区二区在线观看 | 久草资源在线视频 | 国产免费av在线 | av毛片 | 欧美成人精品激情在线观看 | 欧美日韩专区 | 国产高清免费视频 | 日韩在线国产精品 | 98成人网|