Kotlin 结构化并发

446 阅读3分钟

一、核心概念与机制

结构化并发通过‌协程作用域(CoroutineScope) ‌ 管理协程生命周期,确保所有子协程均在父协程的上下文中执行。核心特性包括:

  1. 父子协程关系
    父协程取消时,所有子协程自动取消2。
  2. 错误传播机制
    子协程抛出未捕获异常时,父协程及兄弟协程会被取消2。
  3. 资源自动释放
    协程作用域结束时,所有未完成的协程自动终止,避免内存泄漏26。

二、典型场景与示例


场景 1:界面生命周期绑定

应用场景
在 Android 中,Activity/Fragment 销毁时需取消所有未完成的异步任务(如网络请求、数据库查询)。
实现方式
通过 lifecycleScopeviewModelScope 绑定协程生命周期。
示例代码

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleScope.launch { // ✅ 绑定 Activity 生命周期
            fetchData().collect { data ->
                updateUI(data)
            }
        }
    }

    private fun fetchData(): Flow<Data> = flow {
        // 模拟耗时请求
        delay(2000)
        emit(Data())
    }
}

关键点

  • 当 Activity 销毁时,lifecycleScope 自动取消协程,无需手动调用 cancel()26。

场景 2:多任务协同执行

应用场景
同时执行多个子任务(如并发请求接口 A 和接口 B),需统一管理任务状态。
实现方式
使用 coroutineScope 包裹多个子协程,实现任务分组管理。
示例代码

suspend fun fetchUserData() = coroutineScope { // ✅ 结构化作用域
    val userDeferred = async { api.getUser() }
    val postsDeferred = async { api.getPosts() }

    val user = userDeferred.await()
    val posts = postsDeferred.await()
    
    combineData(user, posts)
}

关键点

  • 若任一子协程失败,coroutineScope 会取消所有子协程并抛出异常24。

场景 3:异常隔离与恢复

应用场景
处理部分子协程失败时不影响其他协程执行(如下载多个文件)。
实现方式
使用 supervisorScope 结合 CoroutineExceptionHandler
示例代码

val handler = CoroutineExceptionHandler { _, e ->
    println("捕获异常: $e")
}

suspend fun downloadFiles() = supervisorScope { // ✅ 异常隔离作用域
    launch(handler) { downloadFile("file1.txt") }
    launch(handler) { downloadFile("file2.txt") }
}

private suspend fun downloadFile(name: String) {
    // 模拟可能失败的下载
    if (Random.nextBoolean()) throw IOException("下载失败")
}

关键点

  • supervisorScope 允许子协程独立失败,不影响其他协程24。

场景 4:流式数据处理

应用场景
处理连续数据流(如实时传感器数据),需确保资源及时释放。
实现方式
通过 launchIn 绑定 Flow 到指定协程作用域。
示例代码

fun observeSensorData() {
    val scope = CoroutineScope(Dispatchers.IO)
    sensorFlow
        .onEach { processData(it) }
        .launchIn(scope) // ✅ 结构化并发收集

    // 手动控制作用域生命周期
    scope.cancel() // 停止所有流处理
}

关键点

  • 手动管理 CoroutineScope 可精确控制 Flow 的生命周期26。

三、对比总结

场景适用操作核心优势关联机制
界面生命周期管理lifecycleScope/viewModelScope自动取消,避免内存泄漏协程作用域绑定26
多任务协同coroutineScope统一异常传播与取消父子协程关系24
异常隔离supervisorScope子协程独立失败异常处理器24
流式数据处理launchIn + 自定义作用域精细控制生命周期Flow 生命周期管理6

通过结构化并发,开发者可避免传统并发模型中常见的资源泄漏和失控线程问题,尤其在异步任务与界面绑定的场景中展现出显著优势