Home > Back-end >  measureTimeMillis produces the same result when being run in a kotlin coroutine
measureTimeMillis produces the same result when being run in a kotlin coroutine

Time:11-01

println always prints 3 s regardless of whether I change the values of delay in the two doXX functions. Both doXX functions take only 2 seconds, why is the result always 3

I think all three coroutines run concurrently, so I increased the delay in the last coroutine to wait for the first two to finish. Then I print the value of the variable time. Here is the code.


  fun main() = runBlocking<Unit> {
        val time = measureTimeMillis {

            launch { doSomethingUsefulOne() }
            launch { doSomethingUsefulTwo() }

        }
    launch {
        delay(6000)
        println("Completed in $time ms")
    }
   }
    suspend fun doSomethingUsefulOne() {
    delay(1000L) 
   }

   suspend fun doSomethingUsefulTwo(){
    delay(1000L) 
  }


If I put them in a child scope of the runBlocking scope, the result is always correct. That is about 2 second.

  fun main() = runBlocking<Unit> {
        val time = measureTimeMillis {
                 doWorld
        }
    
           launch {
        delay(4000)
        println("Completed in $time ms")
    }
   
   }
 suspend fun doWorld() = coroutineScope { // this: CoroutineScope
    launch {
        delay(2000L)
        println("World 2")
    }
    launch {
        delay(1000L)
        println("World 1")
    }
    println("Hello")
}

CodePudding user response:

Check the docs. The example at the top, which is very similar to yours should clarify this and maybe other aspects of coroutines.

The issue is that launch launches a new coroutine and continues. The the block after measureTimeMillis launches 2 coroutines and continues; this takes 3ms to run. The value 3 is stored in time and that's what the 3rd coroutine prints.

CodePudding user response:

You just discovered a feature of coroutines. They run in parallel. Let us look at the code:

fun main() = runBlocking<Unit> {
        val time = measureTimeMillis {

            launch { doSomethingUsefulOne() } // Launches first coroutine does NOT wait
            launch { doSomethingUsefulTwo() } // Launches second coroutine does NOT wait
        } // This block is finished in 3ms, because it only launches the coroutines
    launch {
        delay(6000)
        println("Completed in $time ms")
    }
   }

If you want to wait for both of the coroutines to finish you can wrap them in coroutineScope or runBlocking:

fun main() = runBlocking<Unit> {
        val time = measureTimeMillis {
            runBlocking { // waits for all contained coroutines to finish
                launch { doSomethingUsefulOne() } // Launches first coroutine does NOT wait
                launch { doSomethingUsefulTwo() } // Launches second coroutine does NOT wait
            }
        }
    launch {
        delay(6000)
        println("Completed in $time ms")
    }
   }
  • Related