Kotlin Coroutines - Как задержка в цикле может быть завершена так быстро - PullRequest
1 голос
/ 03 ноября 2019

Я пытаюсь запустить следующий код.

В консоли я вижу, что создано около 8 рабочих потоков, а метод printThread после delay в delayNonBlockingSumOfNumbers() выполняется параллельно между различными потоками. Я не мог понять, как вся операция завершается за 1-2 секунды.

Я полагаю, что задержка в 1 секунду фактически будет применена к определенному числу. Чтобы быть точным, 8 активных потоков работают одновременно, поэтому общее время задержки будет 100000 итераций / 8 потоков ~ 12500 итераций / потоков или секунд.

Мой вопрос: почему / как быстро. И что случилось с несколькими блоками задержки, пожалуйста, проясните мое понимание, если это не так.

Я вижу, что сопрограммы считаются легкими потоками,

означает ли этопоток может одновременно обрабатывать несколько задержек выполнения? Почему я говорю это потому, что вывод показывает, что один и тот же поток используется для выполнения несколько раз, как это

Coroutine in a loop execution output

Если это так, как я могу отладить или распечатать процесс выполнения каждого приостановленного блока, который выполняет задержку выполнения, так же, как мы делаем для потоков , а именно. Thread.currentThread (). Name .

Если бы я использовал Thread.sleep (1000) вместо задержки и напечатал поток, в выводе отобразилось бы различие в 1 секунду между каждым выполнением. Точно так же, как я должен отобразить аналогичный вывод из выполнения сопрограммы, где я вижу фактическую задержку, обрабатываемую?

fun delayNonBlockingSumOfNumbers(){

  printThread("Start of delayNonBlockingSumOfNumbers()")
  val deferredList = (1..100000).map {
    GlobalScope.async {
        //printThread("In Async Before Index $it")
        val timetaken:Long = 1000
        delay(timetaken)
        printThread("In Async After Delay Index $it time is -> $timetaken")
        it
    }
  }
 runBlocking {
    val sum = deferredList.sumBy { it.await() }
    printThread("End of delayNonBlockingSumOfNumbers(), sum = $sum")
 }
}

fun printThread(message:String){
  println("$message ${Thread.currentThread().name} ${Instant.now()}")
}

fun main(){
 delayNonBlockingSumOfNumbers()
 Thread.sleep(20_000)
 printThread("End of ")
}

Вывод: с размером 1_000_000, с разницей всего в 3 секунды

1_000_000 coroutine example

Ответы [ 2 ]

2 голосов
/ 03 ноября 2019

как я могу отладить или распечатать процесс выполнения каждого приостановленного блока, который запускает задержку выполнения, так же, как мы делаем для потоков, а именно. Thread.currentThread().name

Все, что вам нужно сделать, это включить режим отладки сопрограмм. Согласно документации , самый простой способ сделать это - с помощью переключателя -ea JVM.

Если вы выполните следующее с -ea:

fun main() {
    measureTimeMillis {
        runBlocking {
            (1..4).forEach {
                launch {
                    println("$it, delaying in ${Thread.currentThread().name}")
                    delay(1000)
                    println("$it, done in ${Thread.currentThread().name}")
                }
            }
        }
    }.also {
        println("Took $it ms")
    }
}

вы должны увидеть вывод следующим образом:

1, delaying in main @coroutine#2
2, delaying in main @coroutine#3
3, delaying in main @coroutine#4
4, delaying in main @coroutine#5
1, done in main @coroutine#2
2, done in main @coroutine#3
3, done in main @coroutine#4
4, done in main @coroutine#5
Took 1099 ms

что случилось с несколькими блоками задержки

Вы запустили 100 000 одновременных сопрограмм, все они одновременно потратили свою 1 секундувремени сна, а затем все они проснулись через 1 секунду, завершив тест. Это то же самое поведение, которое вы должны ожидать от запуска 100 000 потоков и перевода их в спящий режим.

Так же, как поток не занимает ядро ​​ЦП во время сна, так что сопрограмма не занимает поток во время сна.

0 голосов
/ 03 ноября 2019

См. Эту часть вашего кода:

(1..100000).map {
    GlobalScope.async {
    //...
    }
}

, поэтому вы запускаете новую асинхронную сопрограмму для каждого из ваших 100000 элементов. Вот почему ваши задержки не будут накапливаться.

...