一、功能定位与返回值差异
| 特性 | **launch** | **async** |
|---|---|---|
| 核心用途 | 执行无需返回值的异步任务(如日志上传、I/O 操作) | 执行并发任务并汇总结果(如并行网络请求) |
| 返回值类型 | Job(用于协程生命周期控制) | Deferred<T>(延迟结果容器,需 await() 获取值) |
| 典型场景 | 后台任务执行,不依赖结果顺序性 | 多任务并行执行后合并结果4 |
二、异常处理机制对比
-
**
launch的异常传播**
子协程内未捕获的异常会立即传播到父协程,导致整个作用域取消(级联取消)。launch { throw RuntimeException("异常!") // ⚠️ 触发父协程取消 }需通过
try-catch手动捕获异常或使用SupervisorJob隔离异常。 -
**
async的异常延迟抛出**
异常被暂存于Deferred对象中,只有调用await()时才会抛出异常45:val deferred = async { throw RuntimeException("埋伏的异常!") } deferred.await() // ⚠️ 此处才抛出异常若未调用
await(),异常可能被静默忽略。
三、执行方式与代码示例
-
**
launch:无返回值任务**// 启动两个独立任务,不关心执行顺序 val job1 = launch { uploadLogs() } val job2 = launch { saveToLocal() } // 可继续执行其他操作(如更新 UI) -
**
async:并发任务与结果聚合**// 并行请求数据后合并 val dataA = async { fetchFromApiA() } val dataB = async { fetchFromApiB() } val combinedData = DataWrapper(dataA.await(), dataB.await())使用
awaitAll()可简化多任务等待:val results = awaitAll(async { task1() }, async { task2() })
fun main() = runBlocking {
//子协程
val job = launch {
println("coroutine launch start") // 2.进入子协程 按顺序打印此处
delay(10000)
println("coroutine launch end")// 4.deffered 挂起11s 进入子协程 打印此处
}
val deffered = async {
println("coroutine async start")// 3.进入子协程 打印此处
delay(11000)
println("coroutine async end")//4. 进入子协程 打印此处
"李元霸"
}
println("deffered 零 test derre") //1.因前面两个子协程需要耗时 故而首先打印此处
println("deffered 一:${deffered.await()}")//5.deffered 有返回,就打印此处
delay(30000)
println("deffered 二:${deffered.await()}")//6.deffered 有返回,就打印此处
}
四、关键注意事项
-
资源泄漏风险
launch启动的任务若未绑定作用域生命周期,可能导致内存泄漏;async必须调用await()确保结果处理并暴露潜在异常。
-
线程调度策略
- 两者均可指定调度器(如
Dispatchers.IO)优化线程使用; async默认继承父协程上下文,可通过参数覆盖14。
- 两者均可指定调度器(如
-
结构化并发原则
推荐通过coroutineScope或supervisorScope管理并发任务,确保父作用域取消时子协程自动终止14:suspend fun fetchData() = coroutineScope { val data = async { /* ... */ } // 父作用域取消时自动取消 data 任务 }
五、总结对比
| 维度 | **launch** | **async** |
|---|---|---|
| 目标 | 执行即弃型任务 | 获取并发任务结果 |
| 异常时机 | 立即传播导致作用域取消 | 延迟到 await() 抛出 |
| 线程切换 | 依赖调度器配置 | 同 launch |
| 适用场景 | 不依赖结果的独立任务(如埋点、I/O) | 并行任务结果聚合(如多接口请求合并) |
选择原则:
- 优先使用
launch处理无需返回值的异步操作; - 需合并多个并发结果时选择
async+await()