【问题标题】:why runBlocking is not blocking the invoking thread为什么 runBlocking 不阻塞调用线程
【发布时间】:2020-08-06 14:25:30
【问题描述】:

我正在尝试理解 kotlin 中的 runBlocking。

 println("before runBlocking ${Thread.currentThread().name}")

    runBlocking { // but this expression blocks the main thread
        delay(2000L) // non blocking
        println("inside runBlocking ${Thread.currentThread().name}")
        delay(2000L)
    }

    println("after runBlocking ${Thread.currentThread().name}")

输出

before runBlocking main
inside runBlocking main
after runBlocking main

Kotlin 说

  1. runBlocking - Runs a new coroutineblocks the current thread 一直中断直到完成
  2. 调用 runBlocking 的主线程会阻塞,直到 runBlocking 内的协程完成。

第 1 点:- 如果 runBlocking 在上面的示例中阻塞了 main 线程。然后在 runBlocking 我如何再次获得main 线程。

第 2 点:- 如果Runs a new coroutine 在上述陈述中为真,那么为什么它没有在runBlocking 内创建新的coroutine

【问题讨论】:

  • 兄弟,协程不是线程。 2. 通过coroutineContext[CoroutineName] 获取里面的协程名称, 1. 如果没有提供上下文作为参数,runBlocking 通过阻塞父线程(此处为main)在父线程上运行。

标签: kotlin kotlin-coroutines


【解决方案1】:

runBlockingdoc)的签名是

fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T (source)

如果您看到context 参数,它的默认值为EmptyCoroutineContext。因此,当您不传递特定上下文时,默认值是当前线程上的事件循环。由于在运行runBlocking 块之前的当前线程是主线程,所以你在块内运行的任何东西仍然在主线程上。

如果您传递如下的协程上下文,您将在 runBlocking 中的块在不同的线程中运行。

println("before runBlocking ${Thread.currentThread().name}")

runBlocking(Dispatchers.Default) {
    delay(2000L)
    println("inside runBlocking ${Thread.currentThread().name}")
    delay(2000L)
}

println("after runBlocking ${Thread.currentThread().name}")

输出

before runBlocking main
inside runBlocking DefaultDispatcher-worker-1
after runBlocking main

或者,如果您在不传递上下文的情况下启动 runBlocking,但在内部启动协程,如下所示,您会看到它在不同的线程上运行。

println("before runBlocking ${Thread.currentThread().name}")

runBlocking { 
    println("inside runBlocking ${Thread.currentThread().name}")
    delay(2000L) 
    CoroutineScope(Dispatchers.Default).launch {
        println("inside runBlocking coroutineScope ${Thread.currentThread().name}")
    }
    delay(2000L)
}

println("after runBlocking ${Thread.currentThread().name}")

输出

before runBlocking main
inside runBlocking main
inside runBlocking coroutineScope DefaultDispatcher-worker-1
after runBlocking main

【讨论】:

  • 好的,但是为什么它在传递 Dispatchers.Main 时给出异常
  • @naanu Dispatchers.Main 通常与操作 UI 对象(例如 JVM 中的 android)的主线程一起使用,并且您需要在类路径中具有 Android 主线程调度程序才能使其工作。看看源码中的javaDoc
猜你喜欢
  • 2021-10-19
  • 2020-11-08
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 2016-06-26
  • 2021-08-29
相关资源
最近更新 更多