基本概念
import kotlinx.coroutines.*
fun main() {
GlobalScope.launch { // 在后台启动一个新的协程并继续
delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)
println("World!") // 在延迟后打印输出
}
println("Hello,") // 协程已在等待时主线程还在继续
Thread.sleep(2000L) // 阻塞主线程 2 秒钟来保证 JVM 存活
}
本质上,协程是轻量级的线程。可以在单线程中创建大量的协程:
import kotlinx.coroutines.*
fun main() = runBlocking {
repeat(100_000) { // 启动大量的协程
launch {
delay(5000L)
print(".")
}
}
}
挂起函数
挂起函数 ,它不会造成线程阻塞,但是会 挂起 协程,并且只能在协程中使用。例如上例中的delay
import kotlinx.coroutines.*
fun main() = runBlocking {
launch { doWorld() }
println("Hello,")
}
// 这是你的第一个挂起函数
suspend fun doWorld() {
delay(1000L)
println("World!")
}
在协程内部可以像普通函数一样使用挂起函数, 不过其额外特性是,同样可以使用其他挂起函数(如本例中的 delay)来挂起协程的执行。
全局协程像守护线程
GlobalScope.launch {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // 在延迟后退出
这个协程不会阻止JVM退出,类似守护线程一样。
How it's implemented
Kotlin coroutines are implemented as stackless coroutines. They do not rely on the call stack for maintaining state but instead use a state machine.
Key Details:
- When a suspend function is called, the compiler transforms it into a state machine. Each suspension point is represented as a state in this machine.
- The coroutine's state is stored in a Continuation object, which keeps track of where the coroutine should resume execution.
- Kotlin coroutines are M:N threads, meaning multiple coroutines can run on a smaller number of threads (managed by a CoroutineDispatcher).
- The default dispatcher (Dispatchers.Default) uses a thread pool, while Dispatchers.IO is optimized for blocking I/O operations.
Virtual Threads?: No, Kotlin does not use virtual threads. Instead, it uses cooperative multitasking with suspending functions and dispatchers to manage concurrency.