Skip to content

Kotlin 协程

什么是协程

Kotlin 协程是一种轻量级的线程,用于简化异步编程。协程可以在不阻塞线程的情况下执行长时间运行的任务,提供了更简洁的代码结构。

协程与线程的区别

  • 轻量级:协程比线程更轻量,创建和销毁的开销更小,数千个协程可以在单个线程上运行。
  • 非阻塞:协程可以在执行过程中挂起,而线程则会阻塞,导致资源浪费。
  • 调度:协程的调度由 Kotlin 的协程库管理,而线程的调度由操作系统管理,协程可以在多个线程之间灵活切换。

协程的关键字

  • launch:用于启动一个新的协程,返回一个 Job 对象。
  • async:用于启动一个新的协程并返回一个 Deferred 对象,可以用于获取结果。
  • runBlocking:用于在主线程中启动协程,通常用于测试或在 main 函数中。

协程作用域

  • GlobalScope:全局作用域,适用于需要在整个应用程序中运行的协程,但不推荐在大型应用中使用。
  • CoroutineScope:自定义作用域,适用于特定的生命周期,例如在 Activity 或 Fragment 中,确保协程在生命周期结束时被取消。

协程挂起

  • 挂起函数:协程中的挂起是指协程在执行过程中可以暂停,等待某个操作完成后再继续执行。挂起函数以 suspend 关键字标记,允许协程在不阻塞线程的情况下进行长时间的操作。
  • 非阻塞:当协程挂起时,其他协程或代码可以继续执行,这使得资源利用更加高效。
  • 示例delay 函数是一个典型的挂起函数,它会挂起当前协程一段时间,而不会阻塞线程。

协程切换

  • 切换上下文:使用 withContext 函数在不同的上下文中切换协程,例如从 IO 线程切换到主线程。
  • 阻塞与非阻塞runBlocking 会阻塞当前线程,直到协程完成,而 launchasync 则是非阻塞的,允许其他代码继续执行。

异常处理

  • 使用 try-catch 块捕获协程中的异常。
  • 可以使用 CoroutineExceptionHandler 来处理未捕获的异常,确保应用程序的稳定性。

常用协程

  • launch:启动一个新的协程,适合不需要返回结果的场景。
  • async:启动一个新的协程并返回结果,适合需要并发计算的场景。
  • withContext:在指定的上下文中执行代码,适合需要切换线程的场景。
  • delay:挂起当前协程一段时间,适合模拟长时间运行的任务。

示例代码

kotlin
import kotlinx.coroutines.
fun main() = runBlocking {
    val job = launch {
        try {
            repeat(5) { i ->
                println("Coroutine is working $i")
                delay(1000L) // 模拟长时间运行的任务
            }
        } catch (e: Exception) {
            println("Caught an exception: ${e.message}")
        }
    }
    println("Waiting for coroutine to finish...")
    job.join() // 等待协程完成
    println("Coroutine finished.")
}