Why async coroutine don't work with Runtime.exec?

#1
private fun String.ping(): String = this + Runtime.getRuntime().exec("ping $this")
    .inputStream.reader().readLines().first { it.contains("Minimum") }

fun main() {
    val ips = listOf("8.8.8.8", "8.8.4.4", "1.1.1.1", "1.0.0.1")

    runBlocking {
        ips.asSequence().map { async { it.ping() } }.forEach { println(it.await()) }
    }
}

The code above performs ping sequentially one by one.
I expect them all to be executed at the same time.

Windows 10, OpenJDK 12, Kotlin 1.3.30.

#2

The map operation for sequence of ips doesn’t compute the next result until it is requested by forEach.

So the order of processing is following: map starts async operation for the first ip, then forEach awaits it. Then map starts async ping for the second ip and so on.

#3

Ok, I agree.
But if I remove asSequence() then the ping function will still be executed sequentially.
How to make this code run 4 processes with a ping command in parallel?

#4

By default runBlocking doesn’t use any dispatches, so does async function started in the scope of runBlocking, thus each coroutine is dispatched to an event loop in the single thread.

You can specify a dispatcher with the context parameter either in runBlocking or in async, e.g.

runBlocking(Dispatchers.Default) {
    ips.map { async { it.ping() } }.forEach { println(it.await()) }
}