2.協(xié)程的四種啟動(dòng)模式

1.DEFAULT模式

協(xié)程的默認(rèn)啟動(dòng)模式,launch 調(diào)用后,會(huì)立即進(jìn)入待調(diào)度狀態(tài),一旦調(diào)度器 OK 就可以開(kāi)始執(zhí)行

suspend fun main(){
    println(1)
    val job = GlobalScope.launch {
        println(2)
    }
    println(3)
    //job.join()
    println(4)
}

沒(méi)有job.join打印134或者1342
加入job.join輸出是1324
取決于 CPU 對(duì)于當(dāng)前線(xiàn)程與后臺(tái)線(xiàn)程的調(diào)度順序
main運(yùn)行在ui線(xiàn)程,GlobalScope.launch運(yùn)行在DefaultDispatcher-worker線(xiàn)程
1.沒(méi)有job.join()執(zhí)行流程
先打印1,launch調(diào)用后進(jìn)入待調(diào)度狀態(tài),但是此時(shí)調(diào)度器還沒(méi)有ok
打印3,4,如果運(yùn)氣好的話(huà),會(huì)再打印2,然后程序結(jié)束取決于調(diào)度器ok的時(shí)機(jī)
2.有job.join()執(zhí)行流程
先打印1,launch調(diào)用后進(jìn)入待調(diào)度狀態(tài),但是此時(shí)調(diào)度器還沒(méi)有ok
打印3,job.join等待調(diào)度器ok并打印2,最后打印4

2.LAZY模式

launch 后并不會(huì)有任何調(diào)度行為,協(xié)程體也不會(huì)進(jìn)入執(zhí)行狀態(tài),直到我們需要它執(zhí)行的時(shí)候

suspend fun main(){
    println(1)
    val job = GlobalScope.launch(start = CoroutineStart.LAZY ) {
        println(2)
    }
    println(3)
//    job.start()
    job.join()
    println(4)
}

輸出結(jié)果1324
lazy啟動(dòng)模式,launch后沒(méi)有任何調(diào)度,可以通過(guò)job.start()或者job.join()來(lái)觸發(fā)調(diào)度
1.job.join()執(zhí)行流程
先打印1,launch調(diào)用后不會(huì)有調(diào)度行為
打印3,job.join()隱式觸發(fā)調(diào)度行為并等待調(diào)度器ok打印2
最后打印4
2.job.start()執(zhí)行流程
先打印1,launch調(diào)用后不會(huì)有調(diào)度行為
打印3,job.start()顯式觸發(fā)調(diào)度行為,此時(shí)調(diào)度器還沒(méi)ok
打印4,如果運(yùn)氣好的話(huà),會(huì)再打印2,然后程序結(jié)束

3.ATOMIC模式

launch 調(diào)用后,會(huì)立即進(jìn)入待調(diào)度狀態(tài),跟DEFAULT模式相似
不同的是ATOMIC模式調(diào)用cancel,遇到第一個(gè)掛起函數(shù)之前,它的執(zhí)行不會(huì)取消
協(xié)程launch之后會(huì)有四種狀態(tài)
1.待調(diào)度狀態(tài)此時(shí)調(diào)度器還沒(méi)有ok
2.調(diào)度器ok但還未執(zhí)行代碼
3.開(kāi)始執(zhí)行代碼
4.代碼執(zhí)行完畢
協(xié)程取消時(shí)機(jī)不同,結(jié)果不一樣

suspend fun main(){
    println(1)
    val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
        println(2)
    }
    job.cancel()
    println(3)
    delay(1000)//為了讓2打印出來(lái)
}

打印結(jié)果123或者132,取決于調(diào)度器ok的時(shí)機(jī)
如果將start改為CoroutineStart.DEFAULT打印結(jié)果13
修改上面代碼改為寫(xiě)成協(xié)程里面有掛起函數(shù)

suspend fun main(){
    println(1)
    val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
        delay(50)
        println(2)
    }
    job.cancel()
    println(3)
    delay(1000)
}

打印結(jié)果13,delay是一個(gè)掛起函數(shù),suspend 函數(shù)修飾的函數(shù)就是掛起函數(shù)

4.UNDISPATCHED模式

協(xié)程在這種模式下會(huì)直接開(kāi)始在當(dāng)前線(xiàn)程下執(zhí)行,直到第一個(gè)掛起點(diǎn), 不經(jīng)過(guò)任何調(diào)度器即開(kāi)始執(zhí)行協(xié)程體。
遇到掛起點(diǎn)之后的執(zhí)行線(xiàn)程就取決于掛起點(diǎn)本身的邏輯以及上下文當(dāng)中的調(diào)度器

suspend fun main(){
    log(1)
    GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
        log(2)
    }
    log(4)
}

打印124,打印1直接打印2因?yàn)椴唤?jīng)過(guò)任何調(diào)度器即開(kāi)始執(zhí)行協(xié)程體
如果將start改為CoroutineStart.DEFAULT打印結(jié)果14或者142
修改上面代碼加入掛起函數(shù)

suspend fun main(){
    log(1)
    GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
        log(2)
        delay(200)
        log(3)
    }
    log(4)
    Thread.sleep(500)
    log(5)
}

打印如下
21:11:15:782 [main] 1
21:11:16:015 [main] 2
21:11:16:093 [main] 4
21:11:16:343 [DefaultDispatcher-worker-1] 3
21:11:16:608 [main] 5
delay是掛起函數(shù),3打印的線(xiàn)程DefaultDispatcher-worker-1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容