2.协程的四种启动模式

1.DEFAULT模式

协程的默认启动模式,launch 调用后,会立即进入待调度状态,一旦调度器 OK 就可以开始执行

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

没有job.join打印134或者1342
加入job.join输出是1324
取决于 CPU 对于当前线程与后台线程的调度顺序
main运行在ui线程,GlobalScope.launch运行在DefaultDispatcher-worker线程
1.没有job.join()执行流程
先打印1,launch调用后进入待调度状态,但是此时调度器还没有ok
打印3,4,如果运气好的话,会再打印2,然后程序结束取决于调度器ok的时机
2.有job.join()执行流程
先打印1,launch调用后进入待调度状态,但是此时调度器还没有ok
打印3,job.join等待调度器ok并打印2,最后打印4

2.LAZY模式

launch 后并不会有任何调度行为,协程体也不会进入执行状态,直到我们需要它执行的时候

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

输出结果1324
lazy启动模式,launch后没有任何调度,可以通过job.start()或者job.join()来触发调度
1.job.join()执行流程
先打印1,launch调用后不会有调度行为
打印3,job.join()隐式触发调度行为并等待调度器ok打印2
最后打印4
2.job.start()执行流程
先打印1,launch调用后不会有调度行为
打印3,job.start()显式触发调度行为,此时调度器还没ok
打印4,如果运气好的话,会再打印2,然后程序结束

3.ATOMIC模式

launch 调用后,会立即进入待调度状态,跟DEFAULT模式相似
不同的是ATOMIC模式调用cancel,遇到第一个挂起函数之前,它的执行不会取消
协程launch之后会有四种状态
1.待调度状态此时调度器还没有ok
2.调度器ok但还未执行代码
3.开始执行代码
4.代码执行完毕
协程取消时机不同,结果不一样

suspend fun main(){
    println(1)
    val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
        println(2)
    }
    job.cancel()
    println(3)
    delay(1000)//为了让2打印出来
}

打印结果123或者132,取决于调度器ok的时机
如果将start改为CoroutineStart.DEFAULT打印结果13
修改上面代码改为写成协程里面有挂起函数

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

打印结果13,delay是一个挂起函数,suspend 函数修饰的函数就是挂起函数

4.UNDISPATCHED模式

协程在这种模式下会直接开始在当前线程下执行,直到第一个挂起点, 不经过任何调度器即开始执行协程体。
遇到挂起点之后的执行线程就取决于挂起点本身的逻辑以及上下文当中的调度器

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

打印124,打印1直接打印2因为不经过任何调度器即开始执行协程体
如果将start改为CoroutineStart.DEFAULT打印结果14或者142
修改上面代码加入挂起函数

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是挂起函数,3打印的线程DefaultDispatcher-worker-1

你可能感兴趣的:(2.协程的四种启动模式)