精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一文搞懂 @Async 注解原理

開發
一個注解就搞定異步開發,太爽了,不知道大家都在項目中用過 @Async 注解嗎?今天,我們就來聊聊。

一、先寫個Demo

我們直接使用 SpringBoot 搭建個 Demo,首先就是啟動類,加入 @EnableAsync 注解。

這就是個別同學使用 @Async 注解不生效的原因,沒有在啟動類中打開異步的開關。

再寫一個Service,定義一個異步方法async。

@Service
public class TestService {
    public final Logger log = LoggerFactory.getLogger(getClass());
    @Async
    public void async(){
        log.info("異步線程消息輸出:{}",Thread.currentThread().getName());
    }
}

注意:異步方法所在的類需要被 spring 管理。

定義調用類,上面說了,需要被 spring 管理,所以調用的時候也需要使用注入的方式進行調用,如果使用 new 或者本類方法調用都是不能生效的。

@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    private TestService testService;
    @GetMapping("/async")
    public Object async() throws Exception {
        testService.async();
        return "success";
    }
}

啟動,調用一下看下輸出。

[task-1]c.z.e.encry.service.TestService:異步線程消息輸出:task-1

可以看到,打印該日志的線程已經是另一個線程,且線程名task-1。那么是不是可以猜測一下使用的線程池中線程名稱前綴為task-,這里先提一嘴,后面我們來揭秘。

到了這,我們的 demo 就搭建完成了,下面開始吃源碼吧,源碼之下無秘密,Debug 啟動。

先看一下 @Async 工作流程圖幫助理解。

二、@Async 注解原理

第一步,找到 @Async注解。

注解的內部很簡單,就一個 value 屬性,這個屬性我們后面再說,我先分享一下平常我是如何看源碼的。

  • 首先我會看注釋,尤其是注釋中可以點進去的類,比如 See Also中的我會重點關注。
  • 其次是看注解的參數調用的地方。

通過上面兩步,發現 value 參數調用的類正好與上面標注的 AnnotationAsyncExecutionInterceptor 吻合,所以直接跳到代碼調用的位置。

其實在這里我們就可以直接斷點,然后根據調用棧就知道在哪調用的了。

打個斷點,啟動程序,http 調用異步方法 async。

需要注意,如果你斷點進不來,那就重啟,在應用程序啟動之后的第一次訪問中會被攔住。(原因后面說,在第五節自定義線程池)

點擊圖片中紅框起來的位置,發現跳到的代碼位置正好與 See Also中標注的是同一個方法AsyncExecutionAspectSupport#determineAsyncExecutor ,說明我們沒有找錯地方,那么我們就開始在這個位置,再加入一個斷點,開始我們的 debug 。

AsyncExecutionAspectSupport#determineAsyncExecutor 方法中,其實就是 value 參數生效的地方。

  • 80 行代碼處,獲取注解 @Async 的 value 值。
  • 83 行代碼處,如果有設置的 value 值,去 spring 容器中獲取對應的執行器,對于我們這就是獲取對應的線程池。
  • 85 行代碼處,如果沒有設置 value 值,就返回默認的 defaultExecutor 。

繼續斷點處往下走,所以 AsyncExecutionAspectSupport#determineAsyncExecutor 方法就是返回執行任務的線程池。

  • 如果為空拋出異常(代碼40行)。
  • 否則就封裝我們的異步方法 async 為 Callable。

為什么封裝為一個 Callable 可以評論區聊一下,看看八股文忘了沒有。

繼續往下,就到了代碼 56 行的位置,提交給線程池執行任務。

所以到了這,你看明白了嗎?其實 @Async 注解的核心代碼就是 AsyncExecutionInterceptor#invoke() 方法,只要這個方法主線找到了,邏輯通了,那么@ Async 注解原理還不是手到擒來。

三、底層是不是使用的線程池

回到這個問題上來,底層是不是使用的線程池相信你已經有了答案了吧,在 springboot 中,起碼是使用的線程池。

當 value 屬性值為空時,spring會使用 SimpleAsyncTaskExecutor 執行任務,而該類都是通過 new Thread() 執行任務的,具體可查看 SimpleAsyncTaskExecutor#doExecute(Runnable task) 。

在 AsyncExecutionInterceptor 類中,重寫了父類的 getDefaultExecutor ,當我們沒有指定 value 參數時,就會走到該方法,返回一個applicationTaskExecutor的線程池。

細心的同學應該看到了吧,此處線程的前綴就是task-,這不就對應我們文章開頭日志輸出的線程名稱了嗎。

四、線程池的配置

那么這個線程池是在哪里初始化的呢?我們也沒有看到初始化的代碼啊?

下面我分享一個找配置的方法,現在我們 beanName 已經知道了,直接全局搜索一下不就好了。

這個還算比較順利,全局一查找,就一個,不就是你嗎。代碼位置(TaskExecutionAutoConfiguration#applicationTaskExecutor)

代碼中就一行,執行的 build ,所以我們直接進入。

先看一下 configure,簡簡單單的一波 set 的操作。

所以知道線程池的配置在哪了嗎,那肯定就是 new ThreadPoolTaskExecutor 這了。

在 configure 處打一個斷點,即可看到全部的配置信息,包括線程名稱前綴的指定都在這了。

五、可以自定義線程池嗎

那么可以自定義線程池嗎,當然可以。還記得文章開頭我們提到的 @Async 注解中的 value 屬性嗎,它的值就是指定線程池名稱的。

我們通過一個代碼示例來看下是如何使用自定義線程池的。

上文中我們自定義的線程池,把線程名的前綴改為了zuiyuThreadPool-,如果生效,日志將會打印出線程名稱。

需要注意的就兩點:

  • @Bean 中自定義線程池的注冊bean名稱
  • @Async中指定線程池的名稱,保證與第一步的名稱保持一致。

啟動程序,debug 開始。還記得剛開始我們查找 @Async 注解中value參數使用的地方嗎?這個地方就是獲取我們注解中值的位置。

在 determineAsyncExecutor 方法處,第 80 行 this.getExecutorQualifier(method) 就是獲取注解中值的代碼,此處返回了zuiyuThreadPool。實現是 AnnotationAsyncExecutionInterceptor#getExecutorQualifier。

然后 this.findQualifiedExecutor(this.beanFactory, qualifier) 這一行代碼中,只做了一件事,就是拿著 value 值去 beanFactory 中查找對應的 bean 對象返回。

上面是首次調用的時候的邏輯,注意看上圖的 78 行,所以當你第二次調用的時候就不會走這個邏輯了。

那么這個 executors 是什么呢?點進去看一下。

在此處打個斷點看一下,executors 其實就是一個 map,key 就是注解標注的方法,value 就是該方法對應的線程池。

這就是為什么上文中只有程序第一次啟動的時候才會進入到獲取注解屬性值的方法。

六、返回值怎么獲取

如果想獲取接口的返回值有什么方法嗎?

在@Async 注釋的地方,返回類型只能是 void 或者java.util.concurrent.Future。

所以我們只需要把異步的方法,改為這兩種形式的返回值即可。

假如我們想返回 String 類型的值,可以這樣做。

如上圖,我們把異步方法改為 CompletableFuture<String> 的形式就可以返回 String 類型的值了,使用Funture.get() 方法就可以讀取到該值。

其實歸根結底還是線程池,你還記得 AsyncExecutionInterceptor#invoke 方法嗎,最后一行代碼不就是 submit 提交任務。

我們把異步的方法封裝為了一個 Callable task,然后提交。

而在 doSubmit 方法中,校驗方法返回值類型是不是Future類型,如果不是直接提交任務,返回 null。

所以,知道為什么在異步方法中需要封裝為 Future 了吧,如果不封裝為Future類型,返回為 null,是獲取不到結果的。

總結

@Async 注解的工作原理就是文章開頭給出流程圖所示的流程。核心代碼就是AsyncExecutionInterceptor#invoke() ,重點關注 determineAsyncExecutor() 與doSubmit()即可。

大致流程如下:

  1. 從緩存 map 中獲取線程池實例。
  2. 如果緩存中存在,直接返回。
  3. 如果緩存中不存在,判斷是否指定 value值。
  4. 如果指定 value 值,就去 beanFactory 中獲取對應的線程池實例。
  5. 如果沒有指定,value 為空,就獲取 taskExecutor的實例。
  6. 返回線程池實例。

在第5步中,springboot 中如果獲取 taskExecutor 實例時,因為引入了第三方的jar,獲取到了第三方的線程池,可能會遇到意想不到的 bug,這個點是需要注意的。

責任編輯:趙寧寧 來源: 醉魚Java
相關推薦

2023-09-08 08:20:46

ThreadLoca多線程工具

2021-01-13 05:21:59

參數

2021-07-08 10:08:03

DvaJS前端Dva

2023-09-22 10:45:47

云原生云計算

2023-12-15 15:55:24

Linux線程同步

2024-04-12 12:19:08

語言模型AI

2022-03-24 08:51:48

Redis互聯網NoSQL

2021-04-27 19:21:48

HBase原理開源

2021-03-22 10:05:59

netstat命令Linux

2023-09-15 12:00:01

API應用程序接口

2020-04-15 16:30:24

掃碼登錄微信前端

2019-04-03 09:27:01

MySQLInnoDB務ACID

2023-08-24 16:50:45

2024-06-05 11:43:10

2023-04-03 15:04:00

RPCPHP語言

2019-11-19 08:00:00

神經網絡AI人工智能

2022-06-07 10:13:22

前端沙箱對象

2021-06-30 08:45:02

內存管理面試

2022-08-15 15:39:23

JavaScript面向對象數據

2023-10-16 08:16:31

Bean接口類型
點贊
收藏

51CTO技術棧公眾號

一女二男3p波多野结衣| 国产欧美日本在线| 日韩欧美123区| 国产一区二区三区亚洲| 色综合av在线| 干日本少妇视频| 婷婷亚洲一区二区三区| 美日韩一级片在线观看| 久久69精品久久久久久国产越南| 一起草在线视频| 福利一区视频| 亚洲高清免费在线| 亚洲图片在线观看| 香蕉av在线播放| 激情欧美一区二区| 国产成+人+综合+亚洲欧洲| 国产高清在线免费观看| 国产99久久精品一区二区300| 91麻豆精品国产无毒不卡在线观看| 霍思燕三级露全乳照| 免费在线观看av片| 久久青草国产手机看片福利盒子| 91社区国产高清| 国产一区二区视频免费| 精品9999| 久久99久久亚洲国产| 亚洲女优在线观看| 亚洲丁香日韩| 精品国产网站在线观看| 欧美视频亚洲图片| 久久精品超碰| 欧美日韩一区二区在线播放| 成人在线播放网址| 毛片av在线| 国产精品入口麻豆九色| 欧美日韩在线精品| 熟妇人妻中文av无码| 国产一区二区精品久久99| 国产精品久久久久久一区二区| 国产做受高潮漫动| 亚洲啪啪91| 欧美激情高清视频| 欧美卡一卡二卡三| 婷婷伊人综合| 日韩在线观看视频免费| 在线观看日本黄色| 日韩免费视频| 国产一区二区三区日韩欧美| 国产精品20p| 国产日产精品_国产精品毛片| 国产视频丨精品|在线观看| 国产精品九九视频| 六月丁香久久丫| 亚洲精品av在线播放| 中文字幕乱码在线| 日本欧美韩国国产| 国产视频精品在线| 久久久久久久毛片| 成人网18免费网站| 中文字幕国内精品| 尤物在线免费视频| 亚洲女同中文字幕| 欧美黄色片视频| 精品亚洲永久免费| 99在线精品视频在线观看| 91国产精品91| 91porny九色| 日韩高清不卡一区二区三区| 国产精品丝袜高跟| 国产色在线视频| 成人小视频在线| 精品国产免费一区二区三区| 青草久久伊人| 亚洲国产精华液网站w| 一本久久a久久精品vr综合| 毛片在线看网站| 亚洲综合精品久久| 成人免费在线小视频| 日韩一区二区三区免费| 欧美日韩成人高清| 能看毛片的网站| 久久精品亚洲成在人线av网址| 国产丝袜精品视频| 永久免费看片视频教学| 中文字幕av亚洲精品一部二部| 欧美激情一区二区三区久久久| 男女啊啊啊视频| 日韩精品一二三区| 91久久久久久久久久久久久| 国产91麻豆视频| 久久精品在线免费观看| 自拍另类欧美| 一区二区三区电影大全| 在线不卡a资源高清| 国产精品一区二区在线免费观看| 日韩aaa久久蜜桃av| 日韩中文在线视频| 日韩免费一级片| 久久国产精品露脸对白| 国产精品一区二区免费| 91吃瓜网在线观看| 亚洲国产精品影院| 日本中文字幕观看| 色愁久久久久久| 久久精品中文字幕免费mv| 日韩在线观看第一页| 久久国产免费看| 久久九九视频| 男人天堂亚洲| 欧美精品一二三| 亚洲永久精品ww.7491进入| 一区二区在线| 国产精品v日韩精品| 亚洲免费视频网| 亚洲丝袜制服诱惑| 免费黄色一级网站| 看全色黄大色大片免费久久久| 色婷婷综合久久久久中文字幕1| 日韩av片在线播放| 国产成人日日夜夜| 亚洲欧美日韩精品久久久| 亚洲校园激情春色| 精品国产不卡一区二区三区| 国产精品视频看看| 久久久久久黄| 国产在线精品一区二区三区》| 国产美女在线观看| 欧美日韩二区三区| 30一40一50老女人毛片| 欧美激情欧美| 国产精品久久精品| 欧洲成人av| 精品久久在线播放| 日韩www视频| 国产综合色产| 91香蕉视频在线下载| 欧美一区二区三区在线观看免费| 色婷婷一区二区| 亚洲专区区免费| 欧美亚洲视频| 欧美另类高清视频在线| 忘忧草在线影院两性视频| 亚洲国产免费av| 日韩av无码中文字幕| aaa亚洲精品| 欧美午夜小视频| 国产一区福利| 91sa在线看| 香蕉视频免费在线看| 亚洲成a人片在线不卡一二三区| 99riav国产精品视频| 欧美激情视频一区二区三区在线播放 | 国产精品扒开腿做| 国产精品麻豆一区二区三区| 色狠狠色狠狠综合| 在线观看免费黄色网址| 蜜臀av性久久久久av蜜臀妖精| 亚洲二区自拍| 日韩五码电影| 欧美另类在线观看| 免费看黄色一级视频| 五月天一区二区| 一区二区三区免费在线观看视频 | 日本波多野结衣在线| 亚洲成人午夜影院| 一本色道久久综合亚洲精品图片| 午夜在线播放视频欧美| 视频一区视频二区视频三区高| 欧美aaa大片视频一二区| 中文字幕久久亚洲| 国内精品久久久久久久久久久| 亚洲影院理伦片| 日韩精品一区二区三区高清免费| 国产精品一级| 一本一道久久久a久久久精品91| 日本午夜免费一区二区| 九九热精品在线| 日韩精品福利| 欧美日韩三级一区| 久草福利资源在线观看| 97精品久久久久中文字幕 | 欧美日韩在线免费观看视频| 97青娱国产盛宴精品视频| 欧美性受xxxx白人性爽| 日本在线看片免费人成视1000| 日韩精品一区二区三区四区视频| 自拍偷拍欧美亚洲| 国产精品国产三级国产aⅴ原创| 深夜福利网站在线观看| 久久久噜噜噜| 400部精品国偷自产在线观看 | 亚洲精品乱码久久久久久金桔影视 | 亚洲高清免费| 亚洲精品在线视频观看| 极品一区美女高清| 国产精品日韩电影| japanese色国产在线看视频| 伊人激情综合网| 免费观看国产精品| 欧美日韩视频专区在线播放| 日韩 欧美 精品| 国产精品少妇自拍| 国产传媒第一页| 久久成人免费日本黄色| 亚洲图片你懂的| 欧美激情综合五月色丁香| 欧美www视频| 1级黄色大片儿| 精品一区二区三区在线观看视频 | 午夜精品久久久久久久99| 一本一道波多野结衣一区二区| 国产成人av免费在线观看| 久久久久高清精品| 亚洲图片欧美另类| 精品一区二区综合| www.欧美日本| 日韩一区二区免费看| av动漫免费观看| 精品美女久久| 国产中文一区二区| 色播一区二区| 成人深夜直播免费观看| 日本精品裸体写真集在线观看| 国语对白做受69| 18视频在线观看| 久久综合久久88| 尤物网在线观看| 一区二区在线视频| 国外av在线| 亚洲欧美国产一区二区三区| 动漫av一区二区三区| 欧美成人aa大片| 国产伦精品一区二区三区四区 | 精品人妻一区二区三区四区不卡| 欧美在线你懂得| 国产免费一区二区三区四区五区| 精品久久久免费| 日韩av黄色片| 午夜精品一区二区三区免费视频 | 不卡视频一区二区三区| 久久视频社区| 亚洲自拍小视频| 亚洲精品成人一区| 成人欧美一区二区三区黑人| 99综合99| 超碰97网站| 国产精品久久久久av蜜臀 | 不卡视频在线| 亚洲高清视频一区| 91久久夜色精品国产按摩| 亚洲亚洲精品三区日韩精品在线视频 | 久久精品官网| 午夜视频在线瓜伦| 日本欧美久久久久免费播放网| 91淫黄看大片| 久久国产欧美日韩精品| 日韩欧美中文视频| 国产69精品久久777的优势| 怡红院一区二区| 久久婷婷综合激情| 亚洲女优在线观看| 中文字幕在线播放不卡一区| 精品一区在线观看视频| 亚洲午夜久久久久| www欧美在线| 欧美日韩中文字幕一区二区| 91成人在线免费| 日韩欧美卡一卡二| 四虎永久在线精品免费网址| 亚洲免费视频一区二区| 成人h小游戏| 久久精品视频在线播放| 好看的中文字幕在线播放| 57pao成人国产永久免费| 粉嫩av一区二区三区四区五区 | 99热在线只有精品| 亚洲国产精品久久久久秋霞蜜臀| 精品乱码一区二区三四区视频| 尤物九九久久国产精品的分类| 国产在线激情| 91av视频在线免费观看| 成人高清一区| 国产成人看片| 久久美女视频| 成人午夜视频在线观看免费| 亚洲欧美日韩综合国产aⅴ| 五月婷婷六月丁香激情| 国产不卡免费视频| 精品国产成人亚洲午夜福利| 亚洲欧美另类在线| 亚洲天堂一区在线| 91精品国产欧美一区二区18| 亚洲av成人无码网天堂| 日韩中文字幕亚洲| 激情黄产视频在线免费观看| 国产欧美一区二区三区视频 | 亚洲欧美另类中文字幕| 久操视频在线免费播放| 26uuu另类亚洲欧美日本一| 青草综合视频| 久久成人资源| 欧美在线国产| 91最新在线观看| 成人午夜激情影院| 久久成人小视频| 欧美日韩亚洲一区二区三区| 99精品人妻无码专区在线视频区| 亚洲欧美日韩另类| 欧美hdxxx| 成人午夜两性视频| 国产99久久精品一区二区300| 996这里只有精品| 奇米精品一区二区三区在线观看| 亚洲av无码专区在线播放中文| 中文在线一区二区| 国产区一区二区三| 精品久久人人做人人爽| 1024视频在线| 国产成人精品视频在线| 老司机在线精品视频| 50度灰在线观看| 蜜臀av性久久久久蜜臀av麻豆 | 中文字幕一区av| 亚洲GV成人无码久久精品| 精品成人a区在线观看| 二区在线播放| 成人国产精品免费视频| 欧美男男gaytwinkfreevideos| 蜜桃传媒一区二区三区| 国产成人亚洲综合色影视| 国产喷水在线观看| 欧美色爱综合网| 国产午夜在线视频| 欧美最猛黑人xxxx黑人猛叫黄| 成人看片黄a免费看视频| 国产四区在线观看| 国产在线不卡一卡二卡三卡四卡| 免费黄在线观看| 在线观看免费视频综合| 免费国产在线观看| 国产第一区电影| 国产精品一国产精品| 99视频免费播放| 久久久国产精华| 中文字幕第2页| 色七七影院综合| 国产精品麻豆| 日韩中文在线字幕| 国产精品456露脸| 九九视频在线免费观看| 日韩欧美在线网站| av网站大全在线| www 成人av com| 亚洲精品123区| 久久一区二区电影| 欧美性猛交xxxx乱大交极品| 久久精品国产亚洲a∨麻豆| 国产成人在线一区二区| 欧美日韩中文字幕一区二区三区| 韩国中文字幕av| 成人免费一区二区三区在线观看| 国产美女三级无套内谢| 色综合天天综合网国产成人网| 国产精品国产| 黑森林福利视频导航| 国产日韩欧美激情| 国产日产亚洲系列最新| 欧美乱妇40p| 欧美成人一区在线观看| 久久久免费视频网站| 国产拍揄自揄精品视频麻豆| 中文在线观看免费高清| 久热精品视频在线观看| 91国内精品| 99蜜桃臀久久久欧美精品网站| 国产色爱av资源综合区| 91精品视频免费在线观看 | 欧美人体一区二区三区| 亚洲精品视频一区二区三区| 国产精品99久久久久久似苏梦涵| 国产精品6666| 伊人av综合网| 97久久亚洲| 天天操天天爱天天爽| 亚洲美女视频在线| 你懂的在线播放| 成人中文字幕在线观看| 一本久道久久综合狠狠爱| 手机看片福利视频| 欧美不卡在线视频| 丝袜美腿诱惑一区二区三区| 久久久天堂国产精品| 91蜜桃在线免费视频| 91片黄在线观看喷潮| 高清一区二区三区四区五区| 成人中文视频| 欧美精品欧美极品欧美激情| 69久久夜色精品国产69蝌蚪网| 最新欧美色图| 欧美精品在欧美一区二区|