почему runBlocking не блокирует вызывающий поток - PullRequest
3 голосов
/ 23 апреля 2020

Я пытаюсь понять runBlocking в kotlin.

 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 coroutine и blocks the current thread без перерыва до его завершения
  2. Основной поток, вызывающий блоки runBlocking, до завершения сопрограммы внутри runBlocking.

точка 1: - , если runBlocking заблокировал поток main в приведенном выше примере. Затем внутри runBlocking, как я снова получаю поток main.

точка 2: - если Runs a new coroutine истинно в вышеприведенном утверждении, то почему оно не создало новый coroutine внутри runBlocking.

1 Ответ

5 голосов
/ 23 апреля 2020

Подпись runBlocking ( do c) равна

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

Если вы видите параметр context, по умолчанию он имеет значение EmptyCoroutineContext. Следовательно, если вы не передаете указанный c контекст, значением по умолчанию является событие l oop в текущем потоке. Поскольку текущий поток до запуска блока 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
...