kotlin協(xié)程之coroutineScope函數(shù)使用詳解
正文
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return suspendCoroutineUninterceptedOrReturn { uCont -> val coroutine = ScopeCoroutine(uCont.context, uCont, true) coroutine.startUndispatchedOrReturn(coroutine, block) } }
它是一個suspend
函數(shù),創(chuàng)建一個新的協(xié)程作用域,并在該作用域內(nèi)執(zhí)行指定代碼塊,它并不啟動協(xié)程。其存在的目的是進行符合結(jié)構(gòu)化并發(fā)的并行分解(即,將長耗時任務拆分為并發(fā)的多個短耗時任務,并等待所有并發(fā)任務完成后再返回)。
coroutineScope
與runBlocking
的區(qū)別在于runBlocking
會阻塞當前線程,而coroutineScope
會掛起所在的協(xié)程直至其內(nèi)部任務(包括子協(xié)程)執(zhí)行完成,它不會阻塞所在的線程。
coroutineScope
是一個掛起函數(shù),它被掛起后,會轉(zhuǎn)而執(zhí)行之前的子協(xié)程。
fun main() = runBlocking { launch { //launch① delay(1000) //掛起launch① println("test2") } println("test1") coroutineScope { //第一次掛起runBlocking,直至內(nèi)部邏輯完成 launch { //launch② delay(2000) //掛起launch② println("test3") } delay(5000) //delay① //第二次掛起runBlocking println("test4") } println("test5") } //test1 //test2 //test3 //test4 //test5
代碼分析
runBlocking
在main
線程創(chuàng)建并啟動一個阻塞的協(xié)程;- 創(chuàng)建
launch①
子協(xié)程,由于創(chuàng)建協(xié)程是需要一些時間的,并且協(xié)程的創(chuàng)建是由特定的線程來完成,并非是main線程。所以在創(chuàng)建協(xié)程過程中會并行地執(zhí)行后續(xù)代碼。因此test1
被輸出。 - 執(zhí)行到
coroutineScope
函數(shù)時,把runBlocking
掛起,直到內(nèi)部邏輯執(zhí)行完成。 - 然后創(chuàng)建
launch②
協(xié)程,創(chuàng)建過程中執(zhí)行執(zhí)行后續(xù)代碼:delay①
繼續(xù)掛起runBlocking
5s(掛起函數(shù)中調(diào)用掛起函數(shù))。 - 等到
launch①
創(chuàng)建完畢時,把它掛起1s。launch②
創(chuàng)建完畢時,把它掛起2s。 - 此時
runBlocking、launch①、launch②
都是被掛起狀態(tài)。 - 等到1s后
launch①
恢復,輸出test2
;2s后launch②
被恢復,輸出test3
;5s后runBlocking
第二次掛起被恢復,輸出test4
。 - 此時
coroutineScope
中的邏輯已經(jīng)執(zhí)行完成,恢復runBlocking
的第一次掛起,test5
被輸出。
這比較難以理解,下面的案例稍微容易些:
fun main() = runBlocking { launch { println("test3") } println("test1") coroutineScope { //掛起runBlocking,直到內(nèi)部邏輯完成 println("test2") delay(1000) //掛起runBlocking5s println("test4") } println("test5") //必須等待掛起函數(shù)coroutineScope執(zhí)行完畢后才會被執(zhí)行 } //test1 //test2 //test3 //test4 //test5
而如果把coroutineScope
函數(shù)改成delay
函數(shù),會更加容易理解,因為它們都是掛起函數(shù)。
fun main() = runBlocking { launch { delay(1000) println("test2") } println("test1") delay(2000) //掛起runBlocking協(xié)程2s println("test3") } //test1 //test2 //test3
coroutineScope
經(jīng)常用來把一個長耗時的任務拆分成多個子任務,使這些子任務并行執(zhí)行
suspend fun showSomeData() = coroutineScope { val data1 = async { //子任務1 delay(2000) 100 } val data2 = async { //子任務2 delay(3000) 20 } withContext(Dispatchers.Default) { //合并結(jié)果并返回 delay(3000) val random = Random(10) data1.await() + data2.await() + random.nextInt(100) } }
coroutineScope
有如下語義:
- 并行執(zhí)行內(nèi)部任務
data1
、data2
、withContext
- 如果其它任務(
random
)拋出異常,data1
和data2
兩個任務會被取消 - 如果
showSomeData()
被取消,內(nèi)部的data1
、data2
、withContext
都會被取消 - 如果
data1
、data2
失敗,withContext
被取消。
以上就是kotlin協(xié)程之coroutineScope函數(shù)使用詳解的詳細內(nèi)容,更多關于kotlin協(xié)程coroutineScope函數(shù)的資料請關注腳本之家其它相關文章!
相關文章
Android編程實現(xiàn)動態(tài)支持多語言的方法
這篇文章主要介紹了Android編程實現(xiàn)動態(tài)支持多語言的方法,涉及Android資源、控件及屬性相關操作技巧,需要的朋友可以參考下2017-06-06android ListView內(nèi)數(shù)據(jù)的動態(tài)添加與刪除實例代碼
ListView內(nèi)數(shù)據(jù)的動態(tài)添加與刪除2013-03-03Android Studio多渠道打包、自定義打包APK名稱
Android Studio為我們提供了簡便的方法,可以多渠道打包,一次打包所有的渠道包。這篇文章主要介紹了Android Studio多渠道打包、自定義打包APK名稱,需要的朋友可以參考下2018-01-01Android HorizontalScrollView內(nèi)子控件橫向拖拽實例代碼
本文主要介紹Android HorizontalScrollView的使用,這里給大家一個實例來展示HorizontalScrollView內(nèi)子控件橫向拖拽的效果實現(xiàn),有需要的小伙伴可以參考下2016-07-07Android開發(fā)中關于獲取當前Activity的一些思考
這篇文章主要為大家詳細介紹了Android開發(fā)過程中,關于獲取當前Activity的一些思考,感興趣的小伙伴們可以參考一下2016-02-02關于Touch Panel AA區(qū)要做外擴的原因解析
今天小編就為大家分享一篇關于Touch Panel AA區(qū)要做外擴的原因解析,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12