来自kotlin文档
A coroutine is an instance of suspendable computation.
It may suspend its execution in one thread and resume in another one.delay is a special suspending function.
It suspends the coroutine for a specific time.
Suspending a coroutine does not block the underlying thread, but allows other coroutines to run and use the underlying thread for their code.当一个协程挂起时,正在运行的线程可以自由地执行其他协程。例如,当您使用delay()或callSomeAPI()时,它们是异步完成的。
我来自javascript世界。像setTimeout()或fetch()这样的函数是在javascript callstack外部和浏览器环境内部执行的。
但是在我们的kotlin例子中,到底是谁在执行这些方法呢?难道不应该有一个线程来管理这些东西吗?那么,我们是否要启动一个新线程来处理协程中的异步代码呢?
发布于 2021-11-06 20:07:50
这真的取决于暂停的原因是什么。例如,如果我们挂起等待某个IO,那么很可能下面的另一个线程被用来阻塞这个IO。一些IO是基于事件的,所以OS通知我们的应用程序协程可以恢复。但在许多情况下,我们暂停等待另一个协程,例如,我们等待它的完成,或者我们等待对Channel (可挂起队列)的读取/写入。然后,就不需要额外的线程了--其他协程恢复我们的协程。delay()是另一个例子。我不确定它是如何在内部工作的,它肯定取决于目标平台,但我不怀疑它会做忙碌等待;-)我猜操作系统提供了某种计时器事件。
所以再说一次:这要看情况。
发布于 2021-11-09 06:55:13
import kotlinx.coroutines.*
import java.util.concurrent.Executors
suspend fun main(args: Array<String>) {
coroutineScope {
val start = System.currentTimeMillis()
launch(Executors.newSingleThreadExecutor().asCoroutineDispatcher()) { // #1
launch {
println("1 --> : " + (System.currentTimeMillis() - start))
Thread.sleep(1000L)
println("1 <--: " + (System.currentTimeMillis() - start))
}
launch { // #3
println("2 --> : " + (System.currentTimeMillis() - start))
delay(1000L)
println("2 <--: " + (System.currentTimeMillis() - start))
}
}
}
coroutineScope {
val start = System.currentTimeMillis()
launch(Executors.newScheduledThreadPool(8).asCoroutineDispatcher()) { // #2
launch {
println("1` --> : " + (System.currentTimeMillis() - start))
Thread.sleep(1000L)
println("1` <--: " + (System.currentTimeMillis() - start))
}
launch { // #4
println("2` --> : " + (System.currentTimeMillis() - start))
delay(1000L)
println("2` <--: " + (System.currentTimeMillis() - start))
}
}
}
}示例输出:
1 --> : 56
1 <--: 1063
2 --> : 1063
2 <--: 2086
1` --> : 7
2` --> : 8
1` <--: 1012
2` <--: 1012注意#1和#2行,在#1中,我们使用单线程执行器启动协程(类似于Dispatchers.Main),所以协程的后端是单线程,当我们调用阻塞函数Thread.sleep时,在#3中没有更改启动协程,所以在整个启动之后调用#3。
至于#2,同样的事情也会发生,但还有很多剩余的线程可以让#4启动
所以
,但是在我们的kotlin例子中,到底是谁在执行这些方法?难道不应该有一个线程来管理这些东西吗?那么,我们是否要启动一个新线程来处理协程中的异步代码呢?
不是线程,而是CoroutineContext、E.S.P. CoroutineIntercepter,它可以在CoroutineBuilder的参数(比如launch或其他)或父作用域中定义,
所有的东西都不是特定于os/平台的,而是由程序员控制的用户域调度器。
https://stackoverflow.com/questions/69867430
复制相似问题