Kotlin 协程启动方式

在 Kotlin 协程中,主要有三种核心启动方式,每种方式都有其特定的使用场景和特点:

一、协程启动方式

二、启动方式详解

1. launch - 启动不需要返回结果的协程

Kotlin 复制代码
val job = CoroutineScope(Dispatchers.IO).launch {
    // 执行异步操作
    delay(1000)
    println("任务完成")
}

// 控制协程生命周期
job.cancel() // 取消协程
job.join()   // 等待协程完成

特点

  • 返回 Job 对象(无结果值)

  • Fire-and-forget 模式(发后即忘)

  • 适用于后台任务(日志上传、缓存清理等)

2. async - 启动需要返回结果的协程

Kotlin 复制代码
val deferred = CoroutineScope(Dispatchers.Default).async {
    // 执行计算任务
    delay(1000)
    42 // 返回计算结果
}

// 获取结果(会挂起当前协程)
val result = deferred.await()
println("计算结果: $result")

特点

  • 返回 Deferred<T> 对象(继承自 Job)

  • 通过 await() 获取结果(会挂起当前协程)

  • 支持并行任务:

    Kotlin 复制代码
    val result1 = async { fetchDataFromAPI1() }
    val result2 = async { fetchDataFromAPI2() }
    val combined = result1.await() + result2.await()

3. runBlocking - 阻塞式启动协程

Kotlin 复制代码
fun main() {
    runBlocking {
        // 在阻塞协程中执行
        delay(1000)
        println("主线程阻塞1秒")
    }
    println("程序继续执行")
}

特点

  • 阻塞当前线程直到协程完成

  • 主要用于测试、main函数和桥接阻塞代码

  • 禁止在UI线程使用(会导致ANR)

三、启动参数配置

所有启动函数都支持 start 参数:

Kotlin 复制代码
launch(start = CoroutineStart.LAZY) {
    // 延迟启动的协程
}
启动模式 行为描述 使用场景
DEFAULT 立即调度执行(默认) 大多数情况
LAZY 仅在需要时启动(手动调用start/join/await触发) 条件触发任务
ATOMIC 原子性启动(不可取消) 关键初始化操作
UNDISPATCHED 立即在当前线程执行首段代码 优化上下文切换

四、启动方式对比表

特性 launch async runBlocking
返回类型 Job Deferred<T> T(泛型结果)
是否阻塞线程 非阻塞 非阻塞 阻塞当前线程
结果获取 无返回值 await() 获取结果 直接返回结果
异常处理 异常会传播到父协程 异常在await时抛出 异常直接抛出
适用场景 后台任务、事件触发 并行计算、结果聚合 测试、main函数、脚本
取消传播 通过Job控制 通过Deferred控制 不可取消
生命周期 随作用域结束自动取消 随作用域结束自动取消 执行完成后自动结束

五、实践使用

  • 网络请求组合

    Kotlin 复制代码
    suspend fun fetchCombinedData(): CombinedResult = coroutineScope {
        val user = async { api.getUser() }
        val posts = async { api.getPosts() }
        CombinedResult(user.await(), posts.await())
    }
  • 超时控制

    Kotlin 复制代码
    val result = withTimeoutOrNull(3000) {
        async { longRunningTask() }.await()
    } ?: fallbackValue
  • 任务编排

    Kotlin 复制代码
    val job = launch {
        val step1 = async { doStep1() }
        val step2 = async { doStep2(step1.await()) }
        val step3 = async { doStep3(step2.await()) }
        processFinalResult(step3.await())
    }

七、常见问题总结

Q:请解释Kotlin协程的启动方式及其区别?

A

"Kotlin协程有三种核心启动方式:

1. launch - 任务执行器

  • 返回Job对象,用于控制协程生命周期

  • 不返回结果,适用于'发后即忘'场景

  • 示例:后台日志上传、定时清理任务

2. async - 结果获取器

  • 返回Deferred<T>(继承Job),通过await()获取结果

  • 支持并行任务组合,如并发网络请求

  • 示例:同时获取用户资料和好友列表

3. runBlocking - 阻塞桥接器

  • 阻塞当前线程直到协程完成

  • 主要用于测试、main函数和桥接阻塞代码

  • 禁止在Android主线程使用(会导致ANR)

关键区别

维度 launch async runBlocking
返回值
阻塞性 非阻塞 非阻塞 阻塞
使用场景 后台任务 结果聚合 测试/main
相关推荐
zhangfeng113337 分钟前
BiocManager下载失败 R语言 解决办法
开发语言·r语言
CoderYanger1 小时前
MySQL数据库——3.2.1 表的增删查改-查询部分(全列+指定列+去重)
java·开发语言·数据库·mysql·面试·职场和发展
炮院李教员1 小时前
使用Qt Core模块(无GUI依赖),确保程序作为后台服务/daemon运行,与任何GUI完全无交互。
开发语言·qt
歪歪1002 小时前
Qt Creator 打包应用程序时经常会遇到各种问题
开发语言·c++·qt·架构·编辑器
滴滴滴嘟嘟嘟.2 小时前
Qt自定义列表项与QListWidget学习
开发语言·qt·学习
PEI042 小时前
MVCC(多版本并发控制)
java·开发语言·数据库
用户0273851840262 小时前
[Android]RecycleView的item用法
android
熊猫钓鱼>_>2 小时前
2025反爬虫之战札记:从robots.txt到多层防御的攻防进化史
开发语言·c++·爬虫
前行的小黑炭3 小时前
Android :为APK注入“脂肪”,论Android垃圾代码在安全加固中的作用
android·kotlin
牛十二3 小时前
mac-intel操作系统go-stock项目(股票分析工具)安装与配置指南
开发语言·前端·javascript