kotlin - 为什么协程作用域启动由不同的线程运行?

标签 kotlin asynchronous kotlin-coroutines

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

private val started = System.currentTimeMillis()

suspend fun main(args: Array<String>) {
    debug("Start run blocking")
    debug("starting")
    coroutineScope {
        debug("Inside runBlocking")
        val time = measureTimeMillis {
            val one = launch { doSomethingUsefulOne() }
            val two = launch { doSomethingUsefulTwo() }
            debug("awaiting")
//            two.await()
//            one.await()
            debug("Finished")
        }
        debug("time = $time")
    }
    debug("ending")
    debug("End run blocking")
}

suspend fun doSomethingUsefulOne(): Int {
    debug("Inside doSomethingUsefulOne")
    delay(3000L)
    debug("first")
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    debug("Inside doSomethingUsefulTwo")
    delay(1000L)
    debug("second")
    return 29
}
private fun debug(s: String) {
    val elapsed = System.currentTimeMillis() - started
    println("[time elapsed : $elapsed] $s  --  ${Thread.currentThread()}")
}

我正在使用上面的代码来学习协程的行为。我得到的预期行为如下:

[time elapsed : 15] Start run blocking  --  Thread[main,5,main]
[time elapsed : 16] starting  --  Thread[main,5,main]
[time elapsed : 34] Inside runBlocking  --  Thread[main,5,main]
[time elapsed : 77] Inside doSomethingUsefulOne  --  Thread[DefaultDispatcher-worker-1,5,main]
[time elapsed : 80] awaiting  --  Thread[main,5,main]
[time elapsed : 80] Finished  --  Thread[main,5,main]
[time elapsed : 80] Inside doSomethingUsefulTwo  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 80] time = 46  --  Thread[main,5,main]
[time elapsed : 1089] second  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3088] first  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3089] ending  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3089] End run blocking  --  Thread[DefaultDispatcher-worker-2,5,main]

在这里,我无法跟踪启动是如何在不同线程上运行的,因为它应该利用主线程(如果我就在这里)。另外,在 coroutineScope 之外,它的工作线程打印最后 2 条语句,因为这应该由主线程运行。

我想知道我哪里出错了?

最佳答案

您永远不会在此处指定任何协程调度程序来启动您的协程。这 suspend fun main 为您提供一个空上下文(没有调度程序),并且 coroutineScope 也不会添加任何调度程序。

然后您可以使用 launch无需参数即可启动您的 2 个协程。正如医生所说:

If the context does not have any dispatcher nor any other ContinuationInterceptor, then Dispatchers.Default is used.

这意味着您的协程将使用 Dispatchers.Default 进行调度它根据您拥有的 CPU 核心数量提供多个工作线程。

如果您想在主线程上运行这些协程,则可以使用 launch(Dispatchers.Main) (但它仅在 Android 和 JavaFX AFAIK 等特殊环境中可用)。

关于kotlin - 为什么协程作用域启动由不同的线程运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69061403/

相关文章:

javascript - 使用 jQuery 并行执行多个 promise 后等待完成

android - 使用 GlobalScope.launch 和 CoroutineScope().launch 启动协程有区别吗?

Kotlin:如何映射到两个列表

java - 使用位图工厂在可运行程序中以每秒 30 个图像的速度显示 150 个图像,但它很滞后

python - 在 asyncio 事件循环中运行协程和线程 : Errors while exiting

c++ - std::async 正在阻塞/暂停父线程

kotlin - 如何在kotlin中执行阻塞协程调用并指定线程

android - 为什么当协程试图进入 Dispatchers.Main 时应用程序终止?

java - 从 Volley 请求获取返回值

Android Kotlin Retrofit Post 请求输入的数据未发送