首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何理解Kotlin协程?

如何理解Kotlin协程?
EN

Stack Overflow用户
提问于 2019-07-29 02:36:52
回答 2查看 1.6K关注 0票数 8

我已经尝试阅读了Kotlin协程的各种教程和页面,尽管它对我来说是有意义的,但我仍然没有感觉到它被点击了,我还没有准备好用协程编写异步非阻塞代码。我认为我缺少的是一张图表或图片,说明当一段协程代码执行时到底发生了什么,以及以什么顺序执行。这些代码是如何在线程级别运行的?

代码语言:javascript
运行
复制
    launch {
        delay(1000)
        println("World (${currentThread().name})")
    }
    println("Hello (${currentThread().name})")
    sleep(1500)

我的理解是这样的。我很高兴被纠正或给出一个不同的例子来加深我的理解。

Line0:代码在主线程上启动

Line1:在一个新线程上启动一个新的协程(我想是从forkjoin池)

Line2:挂起函数,以便协程挂起并将线程返回到线程池(因此是非阻塞的)

Line5:在主线程上打印

Line6:阻塞主线程1.5秒

Line3:协程恢复执行(不确定这里的哪个线程-与挂起前的线程相同,也可以是不同的线程?)。协程在该线程上打印并结束,因此再次将该线程返回到池。

我遇到的另一个问题是,如果我将整个代码包装在runBlocking { ... }中,底层执行会发生怎样的变化

EN

回答 2

Stack Overflow用户

发布于 2019-07-29 15:26:11

您的代码实际上不会做任何揭示协程的特殊性质的事情。它使两个线程同时执行它们的任务,就像它们在普通Java中所做的那样。

只有当您在已有的线程(例如,主线程)上启动协程时,它才会变得有趣。这是使用runBlocking块实现的事情之一:

代码语言:javascript
运行
复制
runBlocking {
    launch {
        delay(1000)
        println("Hello from the launched coroutine. My thread is "
                + Thread.currentThread().name)
    }
    println("Hello from the top-level coroutine. My thread is "
            + Thread.currentThread().name)
}

这将打印出来

代码语言:javascript
运行
复制
Hello from the top-level coroutine. My thread is main
Hello from the launched coroutine. My thread is main

runBlocking在调用线程上运行一个事件循环,并将对它的引用传播到您在其中启动的所有协程。例如,delay(1000)将向此事件循环发送一个事件,并指示延迟一秒,然后它将挂起协程。这将允许主线程运行launch下面的其余代码。当时间过去时,事件循环将运行事件处理程序,该事件处理程序将依次恢复协程。

一个更有教育意义的例子是启动一个没有任何Dispatcher的协程。这消除了协程看起来像线程的假象,并揭示了它们的真正魔力:通过调用continuation.resume(),您可以使当前线程直接跳到挂起的协程的代码块的中间,所有这些都是使用普通的Java方法调用实现的。我建议学习this answer,在那里可以详细地解释这一点。如果您有兴趣更深入地解释普通的Java方法是如何做到这一点的,我建议您在YouTube上观看罗曼·伊利扎罗夫·explaining this

票数 6
EN

Stack Overflow用户

发布于 2019-07-29 09:33:49

这里有另一个例子:https://kotlinlang.org/docs/reference/coroutines/basics.html#your-first-coroutine

代码语言:javascript
运行
复制
fun main() {
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

上面的代码打印如下:

代码语言:javascript
运行
复制
Hello,
World!

正如您所看到的,尽管代码看起来是同步的,但执行是异步的。这就是协程的全部想法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57243903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档