好的!下面给你整理一篇 一文搞懂 Kotlin 协程 的干货总结,涵盖基础概念、使用方式、常见函数以及注意事项,帮助你快速掌握协程核心内容。
一文搞懂 Kotlin 协程
1️⃣ 协程的概念
Kotlin 协程(Coroutine)是一种 轻量级的线程,它可以在一个线程中执行多个任务,通过挂起(suspend)和恢复(resume)实现异步操作,而不需要创建大量线程。
- 轻量级:同一线程可以运行数千个协程。
- 非阻塞:使用
suspend
函数挂起协程,不阻塞线程。 - 易于组合:协程可以组合异步任务,代码像同步一样顺序写。
2️⃣ 协程的核心概念
概念 | 说明 |
---|---|
CoroutineScope | 协程的作用域,用于管理协程的生命周期。 |
Job | 协程的句柄,用于取消或检查状态。 |
Dispatcher | 协程运行的线程池类型,例如 Dispatchers.Main 、Dispatchers.IO 、Dispatchers.Default 。 |
suspend 函数 | 可挂起函数,支持协程非阻塞调用。 |
launch | 启动协程,不返回结果,返回 Job。 |
async | 启动协程并返回 Deferred,可用于获取结果。 |
3️⃣ 协程的基本用法
3.1 launch 启动协程
import kotlinx.coroutines.*
fun main() = runBlocking {
launch { // 在主线程中启动协程
delay(1000L) // 挂起1秒
println("Hello from coroutine!")
}
println("Hello from main thread!")
}
输出顺序:
Hello from main thread!
Hello from coroutine!
runBlocking
用于在主线程阻塞等待协程完成,通常用于 main 函数或测试。delay()
是挂起函数,不阻塞线程。
3.2 async 与 await
import kotlinx.coroutines.*
fun main() = runBlocking {
val deferred = async {
delay(1000L)
42
}
println("Result: ${deferred.await()}")
}
async
启动协程返回Deferred
,可通过await()
获取结果。- 可以并行执行多个耗时任务,再统一 await。
3.3 协程作用域
fun main() = runBlocking {
coroutineScope { // 创建局部协程作用域
launch { delay(500L); println("Task 1 done") }
launch { delay(1000L); println("Task 2 done") }
}
println("All tasks completed")
}
coroutineScope
会挂起,直到作用域内所有子协程完成。- 可以嵌套作用域,实现结构化并发。
4️⃣ Dispatcher 常用类型
Dispatcher | 用途 |
---|---|
Dispatchers.Main | UI 主线程操作(Android 使用) |
Dispatchers.IO | I/O 密集型任务(文件、网络请求) |
Dispatchers.Default | CPU 密集型任务(复杂计算) |
newSingleThreadContext("MyThread") | 创建单独线程 |
5️⃣ 挂起函数 suspend
- 使用
suspend
定义挂起函数:
suspend fun doSomething(): String {
delay(1000L) // 模拟耗时操作
return "Done"
}
- 挂起函数只能在协程或另一个挂起函数中调用:
fun main() = runBlocking {
println(doSomething())
}
6️⃣ 结构化并发
Kotlin 协程提倡 结构化并发,即:
- 所有子协程依赖于作用域(Scope)
- 父协程取消,子协程自动取消
- 便于管理生命周期和错误处理
7️⃣ 异常处理
fun main() = runBlocking {
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught $exception")
}
val job = GlobalScope.launch(handler) {
throw AssertionError("Oops")
}
job.join()
}
CoroutineExceptionHandler
捕获协程异常。- 注意:
async
异常不会立即抛出,需要await()
时才会抛。
8️⃣ 实用技巧
- 并发执行多个任务
val result = coroutineScope {
val a = async { task1() }
val b = async { task2() }
a.await() + b.await()
}
- 切换线程
withContext(Dispatchers.IO) {
// 执行耗时操作
}
- 取消协程
val job = launch { repeat(1000) { println("Working") } }
delay(500L)
job.cancel() // 取消协程
9️⃣ 总结
- 协程 = 轻量级线程 + 非阻塞异步
- 挂起函数 suspend 是核心,结合
launch
和async
可以实现并发与顺序执行 - 作用域 Scope + Dispatcher 管理协程生命周期和线程
- 结构化并发 保证任务管理有序、安全
- 协程的优势:高并发、资源占用低、写法接近同步
💡 快速记忆口诀:
launch
启动,async
返回结果,suspend
挂起,withContext
切线程,coroutineScope
管理范围。
发表回复