为什么 runBlocking 不会阻塞调用线程

Vik*_*rya 2 kotlin kotlin-coroutines

我正在尝试了解 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}")
Run Code Online (Sandbox Code Playgroud)

输出

before runBlocking main
inside runBlocking main
after runBlocking main
Run Code Online (Sandbox Code Playgroud)

科特林说

  1. runBlocking -Runs a new coroutine并且可blocks the current thread中断直到它完成
  2. 调用 runBlocking 的主线程会阻塞,直到 runBlocking 内的协程完成。

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

第 2 点:-如果Runs a new coroutine上面的语句为真,那么为什么它没有coroutine在runBlocking.

Mad*_*hat 5

runBlocking( doc )的签名是

fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T (source)
Run Code Online (Sandbox Code Playgroud)

如果您看到该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}")
Run Code Online (Sandbox Code Playgroud)

输出

before runBlocking main
inside runBlocking DefaultDispatcher-worker-1
after runBlocking main
Run Code Online (Sandbox Code Playgroud)

或者,如果您在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}")
Run Code Online (Sandbox Code Playgroud)

输出

before runBlocking main
inside runBlocking main
inside runBlocking coroutineScope DefaultDispatcher-worker-1
after runBlocking main
Run Code Online (Sandbox Code Playgroud)