Kotlin 协程基础 #

一、协程概述 #

协程是一种轻量级的线程,可以挂起和恢复执行,而不阻塞线程。

1.1 协程 vs 线程 #

特性 协程 线程
创建成本 极低 较高
内存占用 几KB 几MB
切换成本
数量限制 可创建大量 受限

1.2 协程优势 #

  • 轻量级:可以创建成千上万个协程
  • 简洁:用同步代码写异步逻辑
  • 安全:结构化并发,避免泄漏

二、添加依赖 #

kotlin
// build.gradle.kts
dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
    // Android 需要添加
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
}

三、第一个协程 #

3.1 launch #

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(1000)
        println("World!")
    }
    println("Hello")
}
// 输出:
// Hello
// World!

3.2 runBlocking #

kotlin
fun main() = runBlocking {
    println("Start")
    delay(1000)
    println("End")
}

3.3 GlobalScope #

kotlin
fun main() = runBlocking {
    GlobalScope.launch {
        delay(1000)
        println("Global coroutine")
    }
    
    delay(2000)  // 等待全局协程完成
}

四、suspend 函数 #

4.1 定义 suspend 函数 #

kotlin
suspend fun fetchData(): String {
    delay(1000)  // 模拟网络请求
    return "Data from server"
}

fun main() = runBlocking {
    val data = fetchData()
    println(data)
}

4.2 suspend 函数特点 #

  • 只能在协程或其他 suspend 函数中调用
  • 可以挂起协程而不阻塞线程
  • 挂起后可以恢复执行

4.3 常用 suspend 函数 #

kotlin
// delay:延迟
delay(1000)

// withContext:切换上下文
withContext(Dispatchers.IO) {
    // IO 操作
}

// await:等待 Deferred 结果
val result = async { compute() }.await()

五、协程构建器 #

5.1 launch #

启动新协程,不返回结果:

kotlin
fun main() = runBlocking {
    launch {
        println("Task 1")
    }
    launch {
        println("Task 2")
    }
}

5.2 async #

启动新协程,返回 Deferred:

kotlin
fun main() = runBlocking {
    val deferred = async {
        delay(1000)
        "Result"
    }
    
    println("Waiting...")
    val result = deferred.await()
    println(result)
}

5.3 并行执行 #

kotlin
suspend fun task1(): Int {
    delay(1000)
    return 1
}

suspend fun task2(): Int {
    delay(1000)
    return 2
}

fun main() = runBlocking {
    val time = measureTimeMillis {
        val a = async { task1() }
        val b = async { task2() }
        println("Result: ${a.await() + b.await()}")
    }
    println("Time: $time ms")  // 约 1000ms,而非 2000ms
}

六、协程作用域 #

6.1 CoroutineScope #

kotlin
fun main() = runBlocking {
    coroutineScope {
        launch {
            delay(1000)
            println("Task 1")
        }
        launch {
            delay(500)
            println("Task 2")
        }
    }
    println("All tasks completed")
}

6.2 结构化并发 #

kotlin
fun main() = runBlocking {
    coroutineScope {
        launch {
            delay(1000)
            println("Child 1")
        }
        launch {
            delay(500)
            println("Child 2")
        }
    }
    // 等待所有子协程完成
    println("Parent completed")
}

七、协程上下文 #

7.1 Dispatchers #

kotlin
fun main() = runBlocking {
    launch(Dispatchers.Main) {
        // 主线程(UI 线程)
    }
    
    launch(Dispatchers.IO) {
        // IO 线程池(网络、文件操作)
    }
    
    launch(Dispatchers.Default) {
        // 默认线程池(CPU 密集型)
    }
    
    launch(Dispatchers.Unconfined) {
        // 不限制线程
    }
}

7.2 withContext 切换上下文 #

kotlin
suspend fun loadData(): String {
    return withContext(Dispatchers.IO) {
        // 在 IO 线程执行
        delay(1000)
        "Data"
    }
}

八、Job #

8.1 获取 Job #

kotlin
fun main() = runBlocking {
    val job = launch {
        delay(1000)
        println("Task completed")
    }
    
    job.join()  // 等待协程完成
    println("After join")
}

8.2 Job 状态 #

kotlin
fun main() = runBlocking {
    val job = launch {
        delay(1000)
    }
    
    println("isActive: ${job.isActive}")
    println("isCompleted: ${job.isCompleted}")
    println("isCancelled: ${job.isCancelled}")
    
    job.join()
    
    println("isCompleted after join: ${job.isCompleted}")
}

九、实战示例 #

9.1 模拟网络请求 #

kotlin
suspend fun fetchUser(id: Int): User {
    return withContext(Dispatchers.IO) {
        delay(1000)  // 模拟网络延迟
        User(id, "User $id")
    }
}

suspend fun fetchPosts(userId: Int): List<Post> {
    return withContext(Dispatchers.IO) {
        delay(500)
        listOf(Post(1, "Post 1"), Post(2, "Post 2"))
    }
}

fun main() = runBlocking {
    val user = fetchUser(1)
    println("User: $user")
    
    val posts = fetchPosts(user.id)
    println("Posts: $posts")
}

data class User(val id: Int, val name: String)
data class Post(val id: Int, val title: String)

9.2 并行加载 #

kotlin
suspend fun loadAllData(): AllData {
    return coroutineScope {
        val user = async { fetchUser(1) }
        val posts = async { fetchPosts(1) }
        val comments = async { fetchComments(1) }
        
        AllData(
            user = user.await(),
            posts = posts.await(),
            comments = comments.await()
        )
    }
}

十、最佳实践 #

10.1 使用结构化并发 #

kotlin
// 推荐
fun main() = runBlocking {
    coroutineScope {
        launch { task1() }
        launch { task2() }
    }
}

// 不推荐
fun main() = runBlocking {
    GlobalScope.launch { task1() }
    GlobalScope.launch { task2() }
}

10.2 选择合适的 Dispatcher #

kotlin
// IO 操作
withContext(Dispatchers.IO) { }

// CPU 密集型
withContext(Dispatchers.Default) { }

// UI 更新
withContext(Dispatchers.Main) { }

10.3 使用 suspend 函数 #

kotlin
// 推荐
suspend fun loadData(): Data {
    return withContext(Dispatchers.IO) {
        // ...
    }
}

// 不推荐:使用回调
fun loadData(callback: (Data) -> Unit) {
    thread {
        val data = fetchData()
        callback(data)
    }
}

十一、总结 #

协程基础要点:

概念 说明
launch 启动协程,不返回结果
async 启动协程,返回 Deferred
suspend 挂起函数关键字
runBlocking 阻塞当前线程
coroutineScope 创建协程作用域
Dispatchers 协程调度器

下一步,让我们学习 协程构建器

最后更新:2026-03-27