好的!下面给你整理一篇 一文搞懂 Kotlin 协程 的干货总结,涵盖基础概念、使用方式、常见函数以及注意事项,帮助你快速掌握协程核心内容。


一文搞懂 Kotlin 协程

1️⃣ 协程的概念

Kotlin 协程(Coroutine)是一种 轻量级的线程,它可以在一个线程中执行多个任务,通过挂起(suspend)和恢复(resume)实现异步操作,而不需要创建大量线程。

  • 轻量级:同一线程可以运行数千个协程。
  • 非阻塞:使用 suspend 函数挂起协程,不阻塞线程。
  • 易于组合:协程可以组合异步任务,代码像同步一样顺序写。

2️⃣ 协程的核心概念

概念说明
CoroutineScope协程的作用域,用于管理协程的生命周期。
Job协程的句柄,用于取消或检查状态。
Dispatcher协程运行的线程池类型,例如 Dispatchers.MainDispatchers.IODispatchers.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.MainUI 主线程操作(Android 使用)
Dispatchers.IOI/O 密集型任务(文件、网络请求)
Dispatchers.DefaultCPU 密集型任务(复杂计算)
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️⃣ 实用技巧

  1. 并发执行多个任务
val result = coroutineScope {
    val a = async { task1() }
    val b = async { task2() }
    a.await() + b.await()
}

  1. 切换线程
withContext(Dispatchers.IO) {
    // 执行耗时操作
}

  1. 取消协程
val job = launch { repeat(1000) { println("Working") } }
delay(500L)
job.cancel() // 取消协程


9️⃣ 总结

  • 协程 = 轻量级线程 + 非阻塞异步
  • 挂起函数 suspend 是核心,结合 launchasync 可以实现并发与顺序执行
  • 作用域 Scope + Dispatcher 管理协程生命周期和线程
  • 结构化并发 保证任务管理有序、安全
  • 协程的优势:高并发、资源占用低、写法接近同步

💡 快速记忆口诀

launch 启动,async 返回结果,suspend 挂起,withContext 切线程,coroutineScope 管理范围。