Kotlin: 协程的四种启动模式(CoroutineStart)

点击查看CoroutineStart英文文档

创建协程的三种方式

  1. runBlocking
    运行一个协程并且会阻塞当前线程,直到它完成。

  2. launch
    启动一个新的协程,不会阻塞当前线程,并且返回一个Job,可以取消。

  3. async
    async和await是两个函数,这两个函数在我们使用过程中一般都是成对出现的。
    async用于启动一个异步的协程任务,await用于去得到协程任务结束时返回的结果,结果是通过一个Deferred对象返回的。

    在概念上,async 就类似于 launch。它启动了一个单独的协程,这是一个轻量级的线程并与其它所有的协程一起并发的工作。不同之处在于 launch 返回一个 Job 并且不附带任何结果值,而 async 返回一个 Deferred ------ 一个轻量级的非阻塞 future, 这代表了一个将会在稍后提供结果的 promise。可以使用 .await() 在一个延期的值上得到它的最终结果, 但是 Deferred 也是一个 Job,所以如果需要的话,你可以取消它。

CoroutineStart源码

协程的四种启动模式一:DEFAULT

Default------根据上下文立即调度协程执行。

如果协程上下文的CoroutineDispatcher从CoroutineDispatcher. isdispatchneeded返回' true '

函数,然后协程代码被调度以供稍后执行,而代码被调度

被调用的协程构建器继续执行。

注意Dispatchers。unconstrained总是从它的\[CoroutineDispatcher.isDispatchNeeded返回false

函数,所以用Dispatchers. \*启动协程。unconstrained DEFAULT与使用un分派相同。

如果协程Job在它有机会开始执行之前被取消,那么它将不会启动它的执行,但将以异常完成。

在挂起点的协同程序的可取消性取决于的具体实现细节暂停功能。使用suspenpendcancellablecoroutine实现可取消的挂起函数。

示例

bash 复制代码
fun main() = runBlocking {
    val job = launch (start = CoroutineStart.DEFAULT){
        println("开始执行耗时操作...")
        delay(2000L)
        println("耗时操作结束")
    }
    delay(1000L)
    job.cancel()
    println("任务取消了")
}

运行结果

协程的四种启动模式二:LAZY

仅在需要时才惰性地启动协程。

详细信息请参见相应协程构建器的文档

(如launchCoroutineScope)。launch]和asynccoroutincope .async)。

如果协程Job在它有机会开始执行之前被取消,那么它将不会启动它的执行,但将以异常完成。

bash 复制代码
fun main() = runBlocking {
    val job = async  (start = CoroutineStart.LAZY){
        println("开始执行耗时操作...")
        delay(2000L)
        println("耗时操作结束")
    }
    delay(1000L)
    job.cancel()
    println("任务取消了")
    job.await()
}

运行结果

协程的四种启动模式三:ATOMIC

自动地(即,以一种不可取消的方式)根据上下文调度协程的执行。

这类似于DEFAULT,但是协程在开始执行之前不能被取消。

在挂起点的协程是否可取消,取决于挂起函数如DEFAULT。

@ExperimentalCoroutinesApi //从1.0.0开始,没有稳定性的ETA

bash 复制代码
fun main() = runBlocking {
    val job = async(start = CoroutineStart.ATOMIC) {
        println("开始执行耗时操作...")
        //在挂起点之前不会被取消
        delay(2000L)//这里就是一个挂起点, delay是挂起函数
        println("耗时操作结束")
    }
    delay(1000L)
    job.cancel()
    println("任务取消了")
}

运行结果

协程的四种启动模式四:UNDISPATCHED

立即执行协程,直到它在当前线程中的第一个挂起点

协程是使用dispatchers . unconstrained启动的。但是,当协程从暂停状态恢复时

根据上下文中的CoroutineDispatcher进行分派。

这类似于ATOMIC,因为协程即使已经被取消也会开始执行。

但不同之处在于它在同一个线程中开始执行。

在挂起点的协程是否可取消,取决于挂起函数如DEFAULT。

注:这是一个实验性api。当使用此模式时,协程的执行语义可能会在将来发生变化。

@ExperimentalCoroutinesApi //从1.0.0开始,没有稳定性的ETA

bash 复制代码
fun main() = runBlocking {
    val job = async(context = Dispatchers.IO, start = CoroutineStart.UNDISPATCHED) {
        println("开始执行耗时操作... ${Thread.currentThread().name}")
        //在挂起点之前不会被取消
        delay(2000L)//这里就是一个挂起点, delay是挂起函数
        println("耗时操作结束...${Thread.currentThread().name}")
    }
    delay(1000L)
    job.cancel()
    println("任务取消了...${Thread.currentThread().name}")
}

运行结果

从上图可以看到, async(context = Dispatchers.IO, start = CoroutineStart.UNDISPATCHED) ,但是还在主线程执行的。

推荐

Kotlin:组合挂起函数

相关推荐
alexhilton4 小时前
Room Fts4:全文搜索替代 SQL LIKE
android·kotlin·android jetpack
hai_android9 小时前
把 Android App 打包成系统应用(System App)
android·kotlin·android jetpack
JMchen10 小时前
【Jetpack 内核实战 01】开篇:Jetpack 组件全家桶核心逻辑与专栏完整规划
android·kotlin·android jetpack
骑着蜗牛撵大象32712 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信
hunterandroid12 小时前
Retrofit 网络请求的异常处理与重试策略实战
android
sejinan13 小时前
极致轻量与秒级起播:NativeWasmTv 开源硬核技术解析与升级版体验
android·开源·webview·tv
小羊没烦恼!13 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
mmsx13 小时前
Android 静默失败实录:五个没有日志的线上事故
android·kotlin
hai_android14 小时前
从零实现一个支持跨进程(IPC)的自定义 Toast
android·kotlin·android jetpack
龙腾-虎跃14 小时前
基于 SIP 协议的自研电话终端:FreeSWITCH 语音与视频通信实战
android·音视频·freeswitch·sip协议终端·wertc