Kotlin 协程
什么是协程
Kotlin 协程是一种轻量级的线程,用于简化异步编程。协程可以在不阻塞线程的情况下执行长时间运行的任务,提供了更简洁的代码结构。
协程与线程的区别
- 轻量级:协程比线程更轻量,创建和销毁的开销更小,数千个协程可以在单个线程上运行。
- 非阻塞:协程可以在执行过程中挂起,而线程则会阻塞,导致资源浪费。
- 调度:协程的调度由 Kotlin 的协程库管理,而线程的调度由操作系统管理,协程可以在多个线程之间灵活切换。
协程的关键字
launch
:用于启动一个新的协程,返回一个Job
对象。async
:用于启动一个新的协程并返回一个Deferred
对象,可以用于获取结果。runBlocking
:用于在主线程中启动协程,通常用于测试或在main
函数中。
协程作用域
- GlobalScope:全局作用域,适用于需要在整个应用程序中运行的协程,但不推荐在大型应用中使用。
- CoroutineScope:自定义作用域,适用于特定的生命周期,例如在 Activity 或 Fragment 中,确保协程在生命周期结束时被取消。
协程挂起
- 挂起函数:协程中的挂起是指协程在执行过程中可以暂停,等待某个操作完成后再继续执行。挂起函数以
suspend
关键字标记,允许协程在不阻塞线程的情况下进行长时间的操作。 - 非阻塞:当协程挂起时,其他协程或代码可以继续执行,这使得资源利用更加高效。
- 示例:
delay
函数是一个典型的挂起函数,它会挂起当前协程一段时间,而不会阻塞线程。
协程切换
- 切换上下文:使用
withContext
函数在不同的上下文中切换协程,例如从 IO 线程切换到主线程。 - 阻塞与非阻塞:
runBlocking
会阻塞当前线程,直到协程完成,而launch
和async
则是非阻塞的,允许其他代码继续执行。
异常处理
- 使用
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.")
}