前言
Kotlin 协程(Coroutines)是 Android 和服务端开发者的必备技能。相比 Java 线程,协程更轻量、更易读、更安全。本文带你从零掌握 Kotlin 协程的核心用法。
一、协程 vs 线程
- 线程:操作系统调度,创建成本高(约1MB栈内存)
- 协程:用户态调度,创建成本极低(约几KB),可创建数十万个
// Java 线程:10000个线程会OOM
for (int i = 0; i < 10000; i++) {
new Thread(() -> doWork()).start();
}
// Kotlin 协程:100000个协程轻松运行
repeat(100_000) {
GlobalScope.launch { doWork() }
}
二、第一个协程
import kotlinx.coroutines.*
fun main() = runBlocking {
// 启动协程
launch {
delay(1000) // 非阻塞延迟
println("World!")
}
println("Hello,")
}
// 输出:
// Hello,
// (1秒后) World!
三、协程作用域(CoroutineScope)
// 1. GlobalScope:全局作用域,生命周期跟随应用
GlobalScope.launch {
println("Global scope")
}
// 2. runBlocking:阻塞当前线程直到协程完成
runBlocking {
launch { println("runBlocking") }
}
// 3. coroutineScope:挂起当前协程,等待子协程完成
suspend fun loadData() = coroutineScope {
launch { fetchUser() }
launch { fetchOrders() }
}
// 4. ViewModelScope(Android):跟随 ViewModel 生命周期
viewModelScope.launch {
val data = repository.fetchData()
updateUI(data)
}
四、挂起函数(suspend)
// 挂起函数:可在协程中暂停执行,不阻塞线程
suspend fun fetchUser(): User {
return withContext(Dispatchers.IO) {
// 切换到 IO 线程执行网络请求
api.getUser()
}
}
// 调用挂起函数
fun loadData() = viewModelScope.launch {
showLoading()
val user = fetchUser() // 挂起,等待结果
updateUI(user) // 恢复执行
hideLoading()
}
五、协程调度器(Dispatcher)
// 1. Dispatchers.Main:主线程(UI 操作)
withContext(Dispatchers.Main) {
textView.text = "Updated"
}
// 2. Dispatchers.IO:IO 密集型(网络、数据库)
withContext(Dispatchers.IO) {
val data = api.fetchData()
database.save(data)
}
// 3. Dispatchers.Default:CPU 密集型(排序、计算)
withContext(Dispatchers.Default) {
val sorted = list.sortedBy { it.id }
}
// 4. 自定义线程池
val customDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
withContext(customDispatcher) {
heavyComputation()
}
六、异常处理
// CoroutineExceptionHandler:全局异常捕获
val handler = CoroutineExceptionHandler { _, e ->
println("Caught: $e")
}
val job = GlobalScope.launch(handler) {
throw RuntimeException("Error!")
}
// try-catch:局部异常处理
try {
val result = async {
riskyOperation()
}.await()
} catch (e: Exception) {
handleError(e)
}
七、实战:并发请求
data class User(val id: Int, val name: String)
data class Order(val id: Int, val userId: Int)
suspend fun loadUserData(userId: Int): Pair<User, List<Order>> {
return coroutineScope {
// 并发执行两个请求
val userDeferred = async { fetchUser(userId) }
val ordersDeferred = async { fetchOrders(userId) }
// 等待结果
Pair(userDeferred.await(), ordersDeferred.await())
}
}
// 对比 Java CompletableFuture
// Kotlin 协程写法更简洁,无需回调链
总结
Kotlin 协程让并发编程变得优雅。核心要点:
- 轻量级:可创建数十万协程而不 OOM
结构化并发
-
:作用域自动管理协程生命周期
挂起函数
-
:用同步写法实现异步逻辑
调度器
-
:灵活切换线程,适配不同场景
觉得有帮助请点赞收藏!有问题欢迎评论区交流
文章摘自:https://www.cnblogs.com/czlws/p/19820642/kotlin-coroutines-concurrency-async
