侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

如何启动和取消一个Kotlin协程?

2025-12-12 / 0 评论 / 4 阅读

题目

如何启动和取消一个Kotlin协程?

信息

  • 类型:问答
  • 难度:⭐

考点

协程启动,协程取消,协程作用域

快速回答

启动协程的常用方式:

  • 使用 launch 启动不返回结果的协程
  • 使用 async 启动需要返回结果的协程

取消协程的关键操作:

  • 调用 Job.cancel() 取消单个协程
  • 通过 CoroutineScope.cancel() 取消作用域内所有协程
## 解析

一、协程启动原理

Kotlin协程通过协程构建器启动,需在协程作用域(CoroutineScope)中执行。主要启动方式:

  • launch:启动新协程,不返回结果,返回Job对象用于控制生命周期
  • async:启动新协程,返回Deferred对象(类似Future),可通过await()获取结果

二、代码示例

import kotlinx.coroutines.*

fun main() = runBlocking {
    // 1. 使用 launch 启动协程
    val job = launch {
        repeat(5) { i ->
            delay(500L)
            println("Job: I'm sleeping $i ...")
        }
    }

    // 2. 使用 async 启动协程
    val deferred = async {
        delay(1000L)
        "Hello World"
    }

    delay(1300L)  // 等待一段时间
    job.cancel()  // 取消第一个协程
    println("Job cancelled")

    println("Async result: ${deferred.await()}")  // 获取async结果
}

三、协程取消机制

  • 取消原理:协程取消是协作式的,需在协程内部检查取消状态
  • 关键检查点delay()yield()等挂起函数会自动检查取消
  • 手动检查:使用ensureActive()isActive判断

四、最佳实践

  • 始终在协程中处理可能取消的操作(如IO)
  • 使用try {...} finally {...}释放资源,结合withContext(NonCancellable)执行不可取消操作
  • 避免在finally中调用挂起函数(除非使用NonCancellable

五、常见错误

  • 错误:未处理取消导致资源泄漏
    错误示例:
    launch {
        val file = openFile() // 可能泄漏
        delay(1000) // 可能在此处被取消
        file.close() // 不会执行
    }
    修正方案:
    launch {
        val file = openFile()
        try {
            delay(1000)
        } finally {
            withContext(NonCancellable) { file.close() }
        }
    }
  • 错误:在已取消作用域启动新协程
    错误示例:
    val scope = CoroutineScope(Job())
    scope.cancel()
    scope.launch { ... } // 立即取消

六、扩展知识

  • 结构化并发:通过作用域管理协程生命周期,避免全局泄漏
  • SupervisorJob:子协程失败不影响同级协程
  • 协程上下文:使用Dispatchers.IO等指定调度器