在之前https://www.cnblogs.com/webor2006/p/11731763.html咱們寫過這樣的一個例子,先來回顧一下:
也就是來演示runBlocking與coroutineScope之間的異同點,當時還闡述了一個對它的理論描述,也來回顧一下:
這里再開個篇幅來提出的原因是在於。。這里面有一些深層次的東東需要再次挖掘,而問題的焦點是在:
回到代碼根據這段文字的理解照理應該是這樣的嘛:
結果肯定不是我們現在所質疑的觀點啦,所以這也是需要再單獨拎出來值得探討的東東,這是因為關於runBlocking和coroutineScope是有更加深層的原因的,下面先來闡述一下:
1、runBlocking並非掛起函數;也就是說,調用它的線程會一直位於該函數中,直到協程執行完畢為止。
2、coroutineScope是掛起函數;也就是說,如果其中的協程掛起,那么coroutineScope函數也會掛起。這樣,創建coroutineScope的外層函數就可以繼續在同一個線程中執行了,該線程會【逃離】coroutineScope之外,並且可以做其他一些事情。
咱們來看一下runBlocking函數的定義:
再來看一下coroutineScope函數的定義:
說實話對於上面的理論描述有點難以理解,怎么最終的welcome的輸出是在最后打印的而非咱們預期理解的要立馬打印出來,其實需要這樣來理解:
所以很明顯“welcome”肯定是最后才會被打印出來的,但是!!!貌似上面的有點像是coroutineScope函數阻塞了當前線程,這個觀點又與這個理論貌似矛盾了呀:
其實這個理論是沒任何問題的,就是理解上需要這樣來理解,如下:
如果說coroutineScope是阻塞了當前線程,也就不可能能執行到這句代碼:
所以這也能論證coroutineScope確實是不會阻塞當前線程的,而當跳出到runBlocing代碼時,它里面會有一個事件循環:
當事件發生時則就會觸發事件,也就類似於當休眠完之后就要開始打印語句了,也就相當於事件觸發了,如下:
這也就是為啥這句話能打印出來的原因,也就是說,其coroutinScope的真正流程是它會將調度返回給外層runBlocking里面的代碼,而且是coroutineScope之上的代碼,而非之下的代碼,而welcome為啥是最后才打印的真正原因絕對不是因為coroutinScope將線程的代碼給阻塞了,這一點確實是比較難理解!!
好,下面了解了這些深層次的理論之后,咱們再以更加正確的姿勢來解讀一下整個程序的執行流程:
接下來線程就會碰到coroutineScope掛起函數了:
當遇到掛起函數時,就需要立馬來區分它之上的代碼和之下的代碼,記住一點它之下的代碼一定是需要等待coroutineScope中的協程代碼整個執行完了才能被執行到【如果這個先提觀點不知道那整個流程就確實是比較難解釋了,這個一定得要有這種概念】,而:
另外一點是當線程遇到了掛起函數會立馬從它往上返回,也就是返回到這塊代碼:
接下來由於延時到了,接着coroutineScope中的這段代碼會得到執行:
接着10s過后,里面的協程這塊代碼就會被打印了:
當這個打印完成,則整個coroutineScope中的協程都執行完了,那該掛起函數也就可以退出了,最后就可以執行掛起函數之下的代碼,也就是:
所以:
至此!!整個流程就再次以一個全新的視角分析完了~~ 雖說是比較細節,但是對於整個協程的認知理解是非常之重要的!!