網(wǎng)站首頁 編程語言 正文
正文
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é)程。其存在的目的是進(jìn)行符合結(jié)構(gòu)化并發(fā)的并行分解(即,將長耗時任務(wù)拆分為并發(fā)的多個短耗時任務(wù),并等待所有并發(fā)任務(wù)完成后再返回)。
coroutineScope
與runBlocking
的區(qū)別在于runBlocking
會阻塞當(dāng)前線程,而coroutineScope
會掛起所在的協(xié)程直至其內(nèi)部任務(wù)(包括子協(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①
恢復(fù),輸出test2
;2s后launch②
被恢復(fù),輸出test3
;5s后runBlocking
第二次掛起被恢復(fù),輸出test4
。 - 此時
coroutineScope
中的邏輯已經(jīng)執(zhí)行完成,恢復(fù)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)常用來把一個長耗時的任務(wù)拆分成多個子任務(wù),使這些子任務(wù)并行執(zhí)行
suspend fun showSomeData() = coroutineScope { val data1 = async { //子任務(wù)1 delay(2000) 100 } val data2 = async { //子任務(wù)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)部任務(wù)
data1
、data2
、withContext
- 如果其它任務(wù)(
random
)拋出異常,data1
和data2
兩個任務(wù)會被取消 - 如果
showSomeData()
被取消,內(nèi)部的data1
、data2
、withContext
都會被取消 - 如果
data1
、data2
失敗,withContext
被取消。
原文鏈接:https://www.jianshu.com/p/c357ac7660cb
相關(guān)推薦
- 2022-07-30 SpringBoot的數(shù)據(jù)校驗(@Validated注解)、關(guān)于validation無法導(dǎo)入的問題解
- 2022-08-15 element-ui中el-select低版本清除選項,el-select 要怎么清空已選的數(shù)據(jù),顯
- 2023-03-16 Android虛擬機(jī)Dalvik和ART科普_Android
- 2022-07-14 浮點數(shù)乘法和整形乘除法的效率經(jīng)驗比較_C 語言
- 2022-08-28 SpringBoot 實現(xiàn)自定義的 starter
- 2022-08-28 Go通道channel通過通信共享內(nèi)存_Golang
- 2022-04-19 賭你會懵的C語言指針進(jìn)階數(shù)組場景解析_C 語言
- 2022-08-26 如何利用python在剪貼板上讀取/寫入數(shù)據(jù)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支