Kotlin协程基础
外观
Kotlin协程基础[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
Kotlin协程是一种轻量级的并发编程框架,用于简化异步和非阻塞代码的编写。协程允许开发者以顺序的方式编写异步代码,同时避免传统回调或线程带来的复杂性。它们是Kotlin语言的核心特性之一,特别适合处理I/O密集型或CPU密集型任务。
协程的核心特点包括:
- 轻量级:协程的创建和切换成本远低于线程。
- 结构化并发:通过作用域(CoroutineScope)管理协程的生命周期,避免资源泄漏。
- 挂起函数(Suspend Function):允许协程在等待结果时暂停执行,而不阻塞线程。
基本概念[编辑 | 编辑源代码]
协程构建器[编辑 | 编辑源代码]
Kotlin提供了几种协程构建器来启动协程:
- launch:启动一个不返回结果的协程(适合“发后即忘”任务)。
- async:启动一个返回`Deferred`结果的协程(可通过`await`获取结果)。
- runBlocking:阻塞当前线程直到协程完成(主要用于测试或主函数)。
import kotlinx.coroutines.*
fun main() = runBlocking {
// 使用 launch
val job = launch {
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // 等待协程完成
// 使用 async
val deferred = async {
delay(1000L)
"Result"
}
println("Waiting...")
println(deferred.await()) // 输出: Result
}
输出:
Hello, World! Waiting... Result
挂起函数[编辑 | 编辑源代码]
挂起函数是协程的核心,使用`suspend`关键字标记。它们只能在协程或其他挂起函数中调用。
suspend fun fetchData(): String {
delay(1000L) // 模拟网络请求
return "Data loaded"
}
fun main() = runBlocking {
val data = fetchData()
println(data) // 输出: Data loaded
}
协程上下文与调度器[编辑 | 编辑源代码]
协程上下文(CoroutineContext)决定协程运行的线程或线程池。常见的调度器:
- Dispatchers.Default:适合CPU密集型任务。
- Dispatchers.IO:适合I/O操作。
- Dispatchers.Main(Android):在主线程运行。
fun main() = runBlocking {
launch(Dispatchers.Default) {
println("Running on Default: ${Thread.currentThread().name}")
}
launch(Dispatchers.IO) {
println("Running on IO: ${Thread.currentThread().name}")
}
}
输出(可能):
Running on Default: DefaultDispatcher-worker-1 Running on IO: DefaultDispatcher-worker-2
实际案例[编辑 | 编辑源代码]
并发网络请求[编辑 | 编辑源代码]
以下示例展示如何使用协程并发执行多个网络请求:
suspend fun fetchUser(id: Int): String {
delay(500L) // 模拟网络延迟
return "User$id"
}
fun main() = runBlocking {
val time = measureTimeMillis {
val user1 = async { fetchUser(1) }
val user2 = async { fetchUser(2) }
println("${user1.await()} and ${user2.await()}") // 并发执行
}
println("Completed in $time ms") // 约500ms而非1000ms
}
输出:
User1 and User2 Completed in 503 ms
协程与UI更新(Android示例)[编辑 | 编辑源代码]
在Android中,协程可用于避免主线程阻塞:
// 假设在Activity中
fun loadData() {
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) { // 切换到IO线程
fetchFromNetwork() // 耗时操作
}
updateUI(data) // 自动切换回主线程
}
}
协程生命周期[编辑 | 编辑源代码]
协程的生命周期通过`Job`对象管理,支持取消和状态监听:
示例代码:
fun main() = runBlocking {
val job = launch {
try {
repeat(1000) { i ->
println("Working $i")
delay(100L)
}
} finally {
println("Cleanup resources")
}
}
delay(250L)
job.cancelAndJoin() // 取消协程并等待结束
}
输出:
Working 0 Working 1 Working 2 Cleanup resources
常见问题[编辑 | 编辑源代码]
协程与线程的区别[编辑 | 编辑源代码]
- 协程是逻辑工作单元,线程是系统资源。
- 一个线程可运行多个协程(协程挂起时释放线程资源)。
结构化并发[编辑 | 编辑源代码]
通过`coroutineScope`或`supervisorScope`创建子作用域,子协程失败时父协程可自动取消:
fun main() = runBlocking {
coroutineScope {
launch {
delay(500L)
throw RuntimeException("Failed!")
}
launch {
delay(1000L)
println("This won't execute")
}
}
}
总结[编辑 | 编辑源代码]
Kotlin协程通过挂起函数和结构化并发简化了异步编程。关键要点:
- 使用`launch`/`async`启动协程,`suspend`定义挂起函数。
- 通过调度器(如`Dispatchers.IO`)控制线程行为。
- 通过`Job`管理生命周期,避免资源泄漏。