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
相关推荐
minos.cpp16 分钟前
第一章 OkHttp 是怎么发出一个请求的?——整体流程概览
android·okhttp·面试
慕晨31 分钟前
升级到Android 15+ 以后如何适配Edge-To-Edge?
android
用户20187928316731 分钟前
解析:Android Drawable目录的屏幕密度适配原理
android
云边小贩37 分钟前
C++ STL学习 之 泛型编程
开发语言·c++·学习·类与对象
Lethehong39 分钟前
飞算JavaAI:革新Java开发体验的智能助手
java·开发语言·java开发·飞算javaai炫技赛
-睡到自然醒~1 小时前
[go] 命令模式
java·开发语言·javascript·后端·golang·命令模式
pengyu1 小时前
【Kotlin系统化精讲:柒】 | 数据类型之复合及高级数据类型:构建复杂程序的万能钥匙
android·kotlin
多读书1931 小时前
Java多线程进阶-深入synchronized与CAS
java·开发语言·java-ee
啊阿狸不会拉杆2 小时前
《算法导论》第 24 章 - 单源最短路径
开发语言·数据结构·c++·算法·php
衍余未了2 小时前
Centos9傻瓜式linux部署CRMEB 开源商城系统(PHP)
开发语言·php