как работает сопрограммный поток - PullRequest
1 голос
/ 01 мая 2020

Kotlin говорит

  • Метод runBlocking блокирует текущий поток для ожидания
  • coroutineScope просто приостанавливает работу, освобождая базовый поток для других использований.
  • следовательно, runBlocking - обычная функция, а coroutineScope - функция приостановки
fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }

    coroutineScope { // Creates a coroutine scope
        launch {
            delay(500L) 
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope") // This line will be printed before the nested launch
    }

    println("Coroutine scope is over") // This line is not printed until the nested launch completes
}

в приведенном выше примере я ожидаю: -

  • runBlocking блокирует основной поток и launch будет выполнен, и он достигнет delay(200L)
  • Итак, сопрограмма освобождается и запускается coroutineScope и приходит к delay(500L) & delay(100L)
  • Итак, снова лежащий в основе сопрограмма выпущена, и она должна напечатать println("Coroutine scope is over").

Это то, что я понимаю по runBlocking и coroutineScope. Который не работает, как ожидалось.

Вывод

Task from coroutine scope
Task from runBlocking
Task from nested launch
Coroutine scope is over

Может кто-нибудь любезно объяснить в простом виде, чтобы понять это.

Ответы [ 2 ]

2 голосов
/ 01 мая 2020

Я немного изменил ваш код

fun main() = runBlocking(Dispatchers.Default) {

    var i = 1
    launch {
        println("Task from runBlocking")
        while (i < 10) {
            delay(30L)
            println(i++)
        }
    }

    coroutineScope { // Creates a coroutine scope
        launch {
            delay(200L)
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope") // This line will be printed before the nested launch
    }

    println("Coroutine scope is over")

}

Вывод

Task from runBlocking
1
2
3
Task from coroutine scope
4
5
6
Task from nested launch
Coroutine scope is over
7
8
9

Наблюдение, которое я сделал,

  • задержка (100L) равна приблизительной 3-кратной задержке (30L)

  • задержка (200L) равна приблизительной 6-кратной задержке (30L)

Итак, после печати 3 Task from coroutine scope и после печати 6 Task from nested launch.

, затем точно после этого Coroutine scope is over, но вы все равно можете увидеть напечатанное l oop 7,8,9.

Это потому, что runBlocking coroutineScope ждет, пока все его члены не выполнятся, приостановив базовые потоки. Но поймите, эти потоки сначала работают с членами coroutineScope, а не с runBlocking.

Следовательно, это печать Task from coroutine scope и Task from nested launch до Coroutine scope is over

1 голос
/ 01 мая 2020

launch вызывает выполнение блока асинхронно , поэтому вызов launch немедленно возвращается, и сопрограмма продолжает работать и не ожидает выполнения запущенного блока.

Следовательно, сразу после вызова runBlocking первый и второй launch вызываются один за другим, и сразу после этого сопрограмма приостанавливается на delay(100L).

Через 100 мс сопрограмма возобновляется и печатает «Задача из области сопрограммы», а затем выполнение блока вложенной области сопрограммы заканчивается. Сфера действия coroutine всегда ожидает окончания выполнения всех запущенных заданий, поэтому она ожидает здесь 500 мс.

Между тем выполняются два запущенных блока, поэтому сначала выводится «Task from runBlocking» (после 200 мс от начала), а затем печатается «Задача из вложенного запуска» (через 500 мс от начала).

В конце концов, после завершения внутреннего запущенного задания внутренняя область сопрограммы завершает ожидание и внешняя сопрограмма продолжает и печатает «Объем сопрограммы окончен».

Это история. Надеюсь, это немного поможет понять, как выполняется код и почему порядок печати такой.

...