协程入门(四):启动模式

1,140 阅读3分钟

启动模式

模式 描述
缺省 默认为DEFAULT
DEFAULT 立即等待被调度执行()
ATOMIC 立即等待被调度执行,并且开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点suspend
UNDISPATCHED 立即在当前线程执行协程体内容
LAZY 需要手动触发才会进入等待调度

示例

缺省

协程采用缺省的启动器, 当父协程执行完1,3后就会调度子协程执行2

    /**
     * 启动模式, 缺省时
     *
     * 协程立即等待被调度执行(等待被调度,不是立即执行)
     *
     * 打印:
     * 1
     * 3
     * 2
     */
    @Test
    fun coroutineStart() = runBlocking {
        println("1")
        launch {
            println("2")
        }
        println("3")
        delay(3000)
    }
DEFAULT
    /**
     * DEFAULT启动模式,效果同缺省时一致
     */
    @Test
    fun default() = runBlocking {
        println("1")
        launch( start = CoroutineStart.DEFAULT) {
            println("2")
        }
        println("3")
        delay(3000)
    }
UNDISPATCHED

UNDISPATCHED的协程会立即执行,所以1后先执行2完毕后才能执行到3

    /**
     * UNDISPATCHED启动模式,立即运行该协程体内容(相比其它启动方式少了等待过程)
     *
     * 打印:
     * 1
     * 2
     * 3
     */
    @Test
    fun unDispatched() = runBlocking {
        println("1")
        launch(start = CoroutineStart.UNDISPATCHED) {
            //2优先于3执行
            println("2")
        }
        println("3")
    }
LAZY

lazy如字面意思,懒惰,需要我们主动触发才能进入等待调度阶段,否则不会有机会执行到。

  • 调用 Job.start,主动触发协程的调度执行
  • 调用 Job.join,隐式的触发协程的调度执行
    /**
     * lazy启动方式,需要主动触发才能进入等待调度阶段
     *
     * - 调用 Job.start,主动触发协程的调度执行
     * - 调用 Job.join,隐式的触发协程的调度执行
     *
     * 使用start触发打印出:
     * 1
     * 3
     * 2
     * 使用join触发打印出:
     * 1
     * 2
     * 3
     * 如果下述例子去掉job.start(),则肯定是:
     * 1
     * 3
     */
    @Test
    fun lazy() = runBlocking {
        println("1")
        val job = launch(start = CoroutineStart.LAZY) {
            //2优先于3执行
            println("2")
        }

        //lazy需要手动触发,让其协程进入等待调度阶段
        job.start()
        //join会堵塞当前协程等待job协程执行完毕
        //job.join()
        println("3")
    }

    /**
     * 注意一旦lazy协程体没有通过start执行完毕或者通过cancel取消掉,则runBlocking永远不会退出。
     * runBlocking会等到里面全部协程结束才退出
     *
     * 打印出:
     * 1
     * 3
     * 4
     */
    @Test
    fun lazy2() = runBlocking {
        println("1")
        val job = launch(start = CoroutineStart.LAZY) {
            println("2")
        }
        println("3")
        //job.start()
        //job.cancel()
        delay(3000)
        println("4")
    }
ATOMIC

ATOMIC启动模式,与DEFAULT类似,立即等待被调度执行

区别在于: ATOMIC开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点, DEFAULT执行前可以被取消。

/**
     * ATOMIC启动模式,立即等待被调度执行,并且开始执行前无法被取消,直到执行完毕或者遇到第一个挂起点。
     *
     * 该示例可以看出在同样经过cancel操作后,atomic协程依旧会被启动,而其它则不会启动了
     * 打印出:
     * 1
     * 3
     * atomic run
     */
    @Test
    fun atomic() = runBlocking {
        println("1")
        val job = launch(start = CoroutineStart.ATOMIC) {
            println("atomic run")
        }
        job.cancel()
        println("3")
    }

    /**
     *
     * 该示例演示atomic被cancel后遇到第一个挂起点取消运行的效果
     *
     * 打印出:
     *
     * 1
     * 2
     * atomic run
     * 3
     */
    @Test
    fun atomic2() = runBlocking {
        println("1")
        val job = launch(start = CoroutineStart.ATOMIC) {
            println("atomic run")
            //遇到了挂起点,cancel生效,不会再执行打印atomic end
            delay(3000)
            println("atomic end")
        }
        job.cancel()
        println("2")
        delay(5000)
        println("3")
    }

    /**
     * 该例子可以看出,在未运行前,default,lazy可以被cancel取消,
     * unDidpatcher因为会立即在当前线程执行,所以该例子中的cancel本身没啥意义了
     *
     * 输出:
     * 1
     * unDispatcherJob run
     * 2
     * atomic run
     */
    @Test
    fun atomic3() = runBlocking {
        println("1")
        val job = launch(start = CoroutineStart.ATOMIC) {
            println("atomic run")
        }
        job.cancel()

        val defaultJob = launch(start = CoroutineStart.DEFAULT) {
            println("default run")
        }
        defaultJob.cancel()

        val lazyJob = launch(start = CoroutineStart.LAZY) {
            println("lazyJob run")
        }
        lazyJob.start()
        lazyJob.cancel()

        val unDispatcherJob = launch(start = CoroutineStart.UNDISPATCHED) {
            println("unDispatcherJob run")
        }
        unDispatcherJob.cancel()

        println("2")
    }

微信公众号