第三部分:函数式编程与并发
第 12 章:协程基础
12.1 什么是协程?为什么使用协程?
1. 协程的概念
协程(Coroutine)是 Kotlin 提供的一种轻量级的并发编程模型,用于简化异步和非阻塞代码的编写。与传统线程不同,协程通过挂起(suspend)和恢复(resume)机制实现任务的协作式调度,避免了线程切换的开销。
- 轻量级:一个线程可以运行多个协程,协程的创建和切换成本远低于线程。
- 非阻塞:通过挂起函数(
suspend)实现异步操作,避免回调地狱。 - 结构化并发:通过作用域(
CoroutineScope)管理协程的生命周期,防止资源泄漏。
2. 为什么使用协程?
在传统异步编程中,开发者通常面临以下问题:
- 回调地狱:嵌套的回调函数导致代码难以维护(如 Android 中的
AsyncTask或网络请求回调)。 - 线程管理复杂:手动创建和管理线程池容易引发资源浪费或线程泄漏。
- 同步困难:多线程共享数据时需要复杂的锁机制。
协程通过以下特性解决这些问题:
- 顺序编写异步代码:用同步的方式写异步逻辑,例如:
suspend fun fetchData() { val data = api.getData() // 挂起函数,不阻塞线程 showData(data) // 回到主线程执行 } - 自动线程切换:通过调度器(如
Dispatchers.IO、Dispatchers.Main)指定协程运行的线程。 - 取消支持:协程作用域取消时,所有子协程会自动取消。
3. 协程与线程的对比
| 特性 | 协程 | 线程 |
|---|---|---|
| 创建成本 | 极低(内存占用约几十字节) | 高(默认栈大小 1MB) |
| 切换开销 | 无系统调用,仅挂起/恢复 | 需要内核介入,成本高 |
| 并发数量 | 单线程可运行数千协程 | 受限于硬件和操作系统 |
| 同步机制 | 通过结构化并发避免竞态条件 | 需手动加锁(如 synchronized) |
4. 适用场景
- I/O 密集型任务:网络请求、文件读写。
- UI 编程:Android 主线程更新 UI。
- 并发任务组合:并行请求多个接口后合并结果。
5. 简单示例
import kotlinx.coroutines.*
fun main() = runBlocking { // 启动一个协程作用域
launch { // 在后台启动一个新协程
delay(1000L) // 非阻塞延迟 1 秒
println("World!")
}
println("Hello,") // 主协程继续执行
}
输出:
Hello,
World!
关键点:协程通过
suspend机制让开发者以同步代码风格实现异步逻辑,同时提供高效的资源管理和错误处理机制。
