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

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

開發(fā) 前端
? Spring創(chuàng)建SimpleAsyncTaskExecutor實例來處理Async注解的異步任務(wù),SimpleAsyncTaskExecutor不是一個好的線程池實現(xiàn)類,SimpleAsyncTaskExecutor根據(jù)需要在當(dāng)前線程或者新線程中執(zhí)行異步任務(wù)。

一、前言

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

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

Spring提供了Async注解,就可以幫助我們一行代碼搞定異步方法調(diào)用。Async注解用起來是很爽,但是如果不對其底層實現(xiàn)做深入研究,難免有時候也會心生疑慮,甚至?xí)蚴褂貌划?dāng),遇見一些讓人摸不著頭腦的問題。

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

二、Async注解簡介

Async注解定義源碼

圖片圖片

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

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

Async注解異步調(diào)用實現(xiàn)原理概述

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

AsyncAnnotationAdvisor類是Spring框架中用于處理Async注解的切面,它會在被Async注解標(biāo)識的方法被調(diào)用時,創(chuàng)建一個異步代理對象來執(zhí)行方法。這個異步代理對象會在一個新的線程中調(diào)用被@Async注解標(biāo)識的方法,從而實現(xiàn)方法的異步執(zhí)行。

在AsyncAnnotationAdvisor中,會使用AsyncExecutionInterceptor來處理Async注解。AsyncExecutionInterceptor是實現(xiàn)了MethodInterceptor接口的類,用于攔截被Async注解標(biāo)識的方法的調(diào)用,并在一個新的線程中執(zhí)行這個方法。

通過AOP的方式實現(xiàn)Async注解的異步執(zhí)行,Spring框架可以在方法調(diào)用時動態(tài)地創(chuàng)建代理對象來實現(xiàn)異步執(zhí)行,而不需要在業(yè)務(wù)代碼中顯式地創(chuàng)建新線程。

總的來說,Async注解的實現(xiàn)是通過AOP機(jī)制來實現(xiàn)的,具體的切面類是AsyncAnnotationAdvisor,它利用AsyncExecutionInterceptor來處理被Async注解標(biāo)識的方法的調(diào)用,實現(xiàn)方法的異步執(zhí)行。

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

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

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

AsyncExecutionInterceptor#invokeAsyncExecutionInterceptor#invoke

下圖是determineAsyncExecutor方法實現(xiàn):

圖片圖片

圖片圖片

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

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

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

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

Spring是怎么為Async注解提供默認(rèn)線程池的

Async注解默認(rèn)線程池有下面兩個方法實現(xiàn):   

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

AsyncExecutionInterceptor#getDefaultExecutorAsyncExecutionInterceptor#getDefaultExecutor

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

AsyncExecutionAspectSupport#getDefaultExecutorAsyncExecutionAspectSupport#getDefaultExecutor

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

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

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

圖片圖片

圖片圖片

左圖為TaskExecutionAutoConfiguration,右圖為TaskExecutionProperties

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

四、總結(jié)

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

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

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

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

2024-12-17 00:00:00

Spring線程

2018-06-21 14:46:03

Spring Boot異步調(diào)用

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

異步和多線程的區(qū)別

2022-09-28 14:54:07

Spring注解方式線程池

2024-08-22 10:39:50

@Async注解代理

2025-04-08 00:00:00

@AsyncSpring異步

2023-07-31 08:05:30

Spring任務(wù)調(diào)度

2024-05-07 08:23:03

Spring@Async配置

2025-06-09 01:01:00

2021-11-11 15:25:28

@AsyncJava線程池

2009-07-09 10:28:19

線程池JDK5

2021-08-04 17:20:30

阿里巴巴AsyncJava

2022-11-15 08:10:23

SpringMyBatis底層

2024-03-06 07:52:21

Spring框架響應(yīng)式編程微服務(wù)架構(gòu)

2012-05-15 02:18:31

Java線程池
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产在线精品一区二区 | 欧美激情一区二区 | 欧美久久一级特黄毛片 | av在线天堂| 国产在线拍偷自揄拍视频 | 亚洲成网| 久久久国产精品 | 五十女人一级毛片 | 91一区二区三区在线观看 | 国产精品一区二区久久 | 天天搞天天操 | 日韩欧美国产电影 | 男人的天堂在线视频 | 欧美a区 | 黄色免费在线观看网站 | 亚洲免费在线观看 | 午夜精品久久久 | 久久伊人一区二区 | 久艹网站 | 久久久看 | 在线国产欧美 | 欧美一区二区三区一在线观看 | 成人午夜精品 | 黄色免费av| 男人电影天堂 | 国产资源在线观看 | 亚洲精品乱码久久久久久按摩观 | 精品一区二区三区在线观看国产 | 亚洲三区在线 | 久久久久1| 午夜国产羞羞视频免费网站 | 91 在线| 91精品久久久久久久久久小网站 | 一起操网站| 国产精品免费小视频 | 国产精品久久久久国产a级 欧美日韩国产免费 | 中文字幕日韩欧美一区二区三区 | 九色在线视频 | 国产亚洲精品美女久久久久久久久久 | 成人精品一区二区三区中文字幕 | 欧美午夜在线 |