Я изучаю сопрограммы Kotlin и пытаюсь понять область действия сопрограмм. Согласно руководству Kotlin по структурированному параллелизму ,
Внешняя область видимости не может завершиться до тех пор, пока не завершатся все ее дочерние сопрограммы.
Я создал пример, как показано ниже:
fun exampleCoroutine() {
println("Corutine started")
runBlocking {
launch {
delay(2000)
launch { //child launch
println("nested child")
}
println("parent")
}
launch {
delay(1000)
println("in the second coroutine")
}
println("Hello")
}
}
И я получаю вывод ниже
Corutine started
Hello
in the second coroutine
parent
nested child
Согласно моему пониманию того, как работают области сопрограмм, я предположил, что «вложенный дочерний элемент» будет печатать раньше «родительского». Поскольку это явно не так, я хочу знать, почему «вложенный дочерний элемент» печатается после «родительского».
И если я неправильно понимаю, пожалуйста, поправьте меня.





Из документации запуска :
Запускает новую сопрограмму, не блокируя текущий поток, и возвращает ссылку на сопрограмму как Job.
Другими словами, он запускает сопрограмму и немедленно возвращает ее. Запущенная сопрограмма выполняется асинхронно. Также обратите внимание, что launch не является функцией suspend.
Вы процитировали:
Внешняя область видимости не может завершиться до тех пор, пока не завершатся все ее дочерние сопрограммы.
Глядя на следующий сегмент вашего кода:
launch { // parent launch
delay(2000)
launch { //child launch
println("nested child")
}
println("parent")
}
В этой цитате говорится, что сопрограмма, созданная «родителем» launch, не может завершиться до тех пор, пока не завершится дочерняя сопрограмма, созданная «дочерним элементом» launch. Последний оператор печати в блоке не выполняется при завершении сопрограммы. Сопрограмма завершается, когда блок возвращается, и, как упоминалось в цитате, все дочерние сопрограммы также завершаются.
Вы можете увидеть это лучше, если воспользуетесь ignoreOnCompletion из объектов Job, возвращаемых launch. Например, следующее:
import kotlinx.coroutines.*
fun main(): Unit = runBlocking {
launch {
delay(1000)
launch {
delay(1000)
println("Child-1 end")
}.invokeOnCompletion { println("Child-1 complete") }
println("Parent-1 end")
}.invokeOnCompletion { println("Parent-1 complete") }
launch {
delay(2000)
println("Parent-2 end")
}.invokeOnCompletion { println("Parent-2 complete") }
}
Kotlin Playground: https://pl.kotl.in/Oar099RZs
Выходы:
Parent-1 end
Parent-2 end
Parent-2 complete
Child-1 end
Child-1 complete
Parent-1 complete
Обратите внимание: хотя последний оператор «Родитель-1» выполняется до завершения «Дочернего элемента-1», «Родитель-1» не завершается до тех пор, пока не завершится «Дочерний элемент-1».
Спасибо! Это очень помогло. Я не понимал, как работает «запуск», и это для меня все проясняет.