Kotlin
协程
协程基础

第一个协程

协程是可挂起计算的一个实例,它在概念上类似与线程。但是线程不绑定到任何特定线程。它可以在一个线程中挂起,并在另一个线程中恢复,协程可以被认为是轻量级线程

使用Kotlin中的协程需要导入coroutine依赖

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")

以下是使用一个协程的示例

fun main() = runBlocking {
    launch {
        delay(1000L)
        println("World")
    }
    println("Hello")
}

launch:一个协程构造器,与其它代码同时启动一个新的协程

delay:特殊的挂起函数,将协程暂停指定时间,挂起协程不会阻塞底层,但允许其它协程同时运行

runBlocking:一个协程构造器

runBlocking意味着允许它的线程在调用中被阻塞,直到其中的协程内的程序完成执行。

结构化并发

协程遵循结构化并发原则,新的协程只能在特定的CoroutineScope中启动,这个范围限定了协程的生命周期

挂起函数

可以将launch中的代码提取到一个单独的函数中,这些函数需要被suspend修饰符修饰

挂起函数能够像函数一样在协程内部被调用,但它们的附加功能是可以反过来使用其它挂起函数来挂起协程的执行

fun main() {
    runBlocking {
        launch {
            doCoroutine()
        }
    }
    println("Main thread is running...")
}
 
// 这是一个挂起函数
suspend fun doCoroutine() {
    delay(1000L)
    println("Coroutine is running")
}

作用域构建器

除了不同构造器提供的协程作用域之外,还可以使用coroutineScope申明自己的作用域,它创建一个协程作用域,直到所有启动的子线程完成后才完成

runBlocking将会阻塞当前线程等待,而coroutineScope只是挂起,释放底层线程以供其他用途。runBlocking是常规函数,而coroutineScope是挂起函数

Job

launch构造器将会返回一个Job对象,该对象是启动线程的句柄,可用于显示等待协程完成

fun main() = runBlocking {
    val job = launch {
        delay(10000L)
    }
    println("Hello")
    job.join()
    println("World")
}

协程是轻量级的

协程比JVM线程占用的资源更少,使用JVM时可能会耗尽内存资源的代码可以使用协程来表达,并且不会耗尽内存资源

fun main() = runBlocking {
    repeat(50_000){
        launch {
            delay(5000L)
            println(".")
        }
    }
}