Jem*_*ili 55 kotlin kotlin-coroutines
Kotlin中是否有任何特定的语言实现,它与协同程序的另一种语言实现有所区别?
在这里,我将启动100000个协程,这段代码背后会发生什么?
for(i in 0..100000){
async(CommonPool){
//run long running operations
}
}
Run Code Online (Sandbox Code Playgroud)
Rom*_*rov 56
coroutine就像轻量级线程一样意味着什么?
与线程一样,Coroutine表示与其他协同程序(线程)同时执行的一系列操作.
有什么不同?
线程直接链接到相应OS(操作系统)中的本机线程,并消耗大量资源.特别是,它为其堆栈消耗了大量内存.这就是为什么你不能只创建100k线程.你可能会耗尽内存.线程之间的切换涉及OS内核调度程序,就消耗的CPU周期而言,这是一项非常昂贵的操作.
另一方面,协程纯粹是用户级语言抽象.它不会绑定任何本机资源,并且在最简单的情况下,它只使用JVM堆中的一个相对较小的对象.这就是为什么很容易创建100k协同程序.在协程之间切换根本不涉及OS内核.它可以像调用常规函数一样便宜.
kotlin的协同程序实际上并行/同时运行吗?即使在多核系统中,在任何给定时间只有一个协程运行(是不是?)
一个协程可以运行或暂停.挂起的协程没有与任何特定线程相关联,但是正在运行的协程在某个线程上运行(使用线程是在OS进程内执行任何操作的唯一方法).是否所有运行在同一线程上的协同程序(因此可能只在多核系统中使用单个CPU)或在不同的线程中运行(因此可能使用多个CPU)完全由使用协同程序的程序员掌握.
在Kotlin中,协同程序的调度通过协程上下文来控制.您可以在"kotlinx.coroutines指南"中阅读更多相关内容
在这里,我将启动100000个协程,这段代码背后会发生什么?
假设您正在使用项目中的launch函数和CommonPool上下文kotlinx.coroutines(这是开源的),您可以在此处检查它们的源代码:
launch在这里定义https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.ktCommonPool在这里定义https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt在launch刚刚创造了新的协同程序,同时CommonPool调度的协同程序到ForkJoinPool.commonPool()其确实使用多个线程,因此在本例中多个CPU执行.
launch调用之后的代码{...}称为挂起lambda.它是什么以及如何暂停lambdas和函数实现(编译)以及标准库函数和类之类startCoroutines,suspendCoroutine并CoroutineContext在相应的Kotlin协程设计文档中进行了解释.
Rus*_*lan 47
由于我只在JVM上使用协同程序,我将讨论JVM后端,还有Kotlin Native和Kotlin JavaScript,但Kotlin的这些后端超出了我的范围.
让我们首先将Kotlin协程与其他语言协程进行比较.基本上,你应该知道有两种类型的协同程序:无堆栈和堆栈.Kotlin实现了无堆栈协程 - 这意味着协程没有自己的堆栈,这限制了协同程序可以做的一点点.你可以在这里阅读一个很好的解释.
例子:
coroutine就像轻量级线程一样意味着什么?
这意味着Kotlin中的协程没有自己的堆栈,它不映射到本机线程,它不需要在处理器上进行上下文切换.
有什么不同?
线程 - 抢先式多任务处理.(通常).协同 - 合作多任务.
线程 - 由OS(通常)管理.协同程序 - 由用户管理.
kotlin的协程实际上并行/同时运行吗?
这取决于你可以在自己的线程中运行每个协同程序,或者你可以在一个线程或一些固定的线程池中运行所有协同程序.
更多关于coroutines如何在这里执行.
即使在多核系统中,在任何给定时间只有一个协程运行(是不是?)
不,请看上一个答案.
在这里,我将启动100000个协程,这段代码背后会发生什么?
实际上,这取决于.但假设您编写以下代码:
fun main(args: Array<String>) {
for (i in 0..100000) {
async(CommonPool) {
delay(1000)
}
}
}
Run Code Online (Sandbox Code Playgroud)
此代码立即执行.
因为我们需要等待async来电的结果.
所以让我们解决这个问题:
fun main(args: Array<String>) = runBlocking {
for (i in 0..100000) {
val job = async(CommonPool) {
delay(1)
println(i)
}
job.join()
}
}
Run Code Online (Sandbox Code Playgroud)
运行此程序时,kotlin将创建2*100000个实例Continuation,这将占用几十Mb的RAM,在控制台中,您将看到1到100000的数字.
所以让我们以这种方式重写这段代码:
fun main(args: Array<String>) = runBlocking {
val job = async(CommonPool) {
for (i in 0..100000) {
delay(1)
println(i)
}
}
job.join()
}
Run Code Online (Sandbox Code Playgroud)
我们现在取得了什么?现在我们只创建了100001个实例Continuation,这要好得多.
每个创建的Continuation都将在CommonPool(这是ForkJoinPool的静态实例)上调度和执行.
| 归档时间: |
|
| 查看次数: |
12411 次 |
| 最近记录: |