kotlin: 协程的启动模式: ATOMIC

一,例一:atomic模式启动

代码:

        //处理按钮点击事件
        binding.button3.setOnClickListener {
            runBlocking {
                log(1)
                val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
                    log(2)
                }
                job.cancel()
                log(3)
            }
        }

运行结果:

image

我们创建了协程后立即 cancel,但由于是 ATOMIC 模式,
因此协程一定会被调度,因此 1、2、3 一定都会输出

二,例二,比较default模式

代码:

        //处理按钮点击事件
        binding.button4.setOnClickListener {
            runBlocking {
                log(1)
                val job = GlobalScope.launch(start = CoroutineStart.DEFAULT) {
                    log(2)
                }
                job.cancel()
                log(3)
            }
        }

运行结果:

image

这次是 DEFAULT 模式,
在第一次调度该协程时如果 cancel 就已经调用,那么协程就会直接被 cancel 而不会有任何调用,
当然也有可能协程开始时尚未被 cancel,那么它就可以正常启动了。
所以改用 DEFAULT 模式后,2 有可能会输出,也可能不会

三,例三

代码:

        //处理按钮点击事件
        binding.button5.setOnClickListener {
            runBlocking {
                log(1)
                val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
                    log(2)
                    delay(1000)
                    log(3)
                }
                job.cancel()
                log(4)
                job.join()
            }
        }

运行结果:

image

cancel 调用一定会将该 job 的状态置为 cancelling,只不过ATOMIC 模式的协程在启动时无视了这一状态

delay 会使得协程体的执行被挂起,1000ms 之后再次调度后面的部分,因此 3 会在 2 执行之后 1000ms 时输出。
对于 ATOMIC 模式,我们已经讨论过它一定会被启动,
实际上在遇到第一个挂起点之前,它的执行是不会停止的,
delay 是一个 suspend 函数,
这时我们的协程迎来了自己的第一个挂起点,
恰好 delay 是支持 cancel 的,因此后面的 3 将不会被打印
posted @ 2025-08-09 13:40  刘宏缔的架构森林  阅读(10)  评论(0)    收藏  举报