Kotlin 异步函数不是 运行 并行

Kotlin async function not run in parallel

我有一个 kotlin 函数,如下所示,我希望它可以将同步 IO 操作包装到异步中。

suspend fun <T> runIOAsync(f:suspend () -> T): Deferred<T> = coroutineScope{
    async(Dispatchers.IO) {
       f()
    }
}

然后我在调用方有我的代码

 runBlocking {
            repeat(5) {
                runIOAsync {
                    println(it)
                    println(Thread.currentThread())
                    Thread.sleep(3000)
                    println("After sleep $it")
                }.await()
            }
        }

但实际输出是

0
Thread[DefaultDispatcher-worker-1 @coroutine#2,5,main]
After sleep 0
1
Thread[DefaultDispatcher-worker-1 @coroutine#3,5,main]
After sleep 1
2
Thread[DefaultDispatcher-worker-1 @coroutine#4,5,main]
After sleep 2
3
Thread[DefaultDispatcher-worker-1 @coroutine#5,5,main]
After sleep 3
4
Thread[DefaultDispatcher-worker-1 @coroutine#6,5,main]
After sleep 4

我的函数中的所有任务似乎都是串行执行的。哪位大神帮忙解释一下

我们暂时搁置runIOAsync

您在调用 async() 后立即使用 await(),这意味着您实际上是在等待异步执行结束,然后再执行下一个。

相反,先启动所有任务,然后等待所有任务。例如,您可以使用 awaitAll:

runBlocking {
    List(5) {
        async(Dispatchers.IO) {
            println(it)
            println(Thread.currentThread())
            Thread.sleep(3000)
            println("After sleep $it")
        }
    }.awaitAll()
}

此外,您在 runIOAsync 中封装作用域的方式是错误的,即使不调用 await(),您也会等待异步执行结束(coroutineScope一个挂起函数,在恢复之前等待其所有子协程。

相反,使用 coroutineScope 来定义协程执行的边界,您甚至不必 await 它们。由于您不需要从此代码中获取值,因此您也可以在此处使用 launch 而不是 async

coroutineScope {
    repeat(5) {
        launch(Dispatchers.IO) {
            println(it)
            println(Thread.currentThread())
            Thread.sleep(3000)
            println("After sleep $it")
        }
    }
}

声明一个 suspend 函数 return 一个 Deferred 应该是一个危险信号,从 API 的角度来看是相当混乱的:如果你暂停它意味着你等等,如果你 return Deferred 这意味着你不等待(你立即 return 一些 运行ning 计算的句柄)。两者兼顾的函数会很奇怪。

如果你想要从 IO 绑定代码中创建挂起代码,你可以使用现有的 withContext 函数:

// this suspends until the code inside is done
withContext(Dispatchers.IO) {
    // run some blocking IO code
}

但是请注意,这与定义并发代码无关。如果你想同时 运行 多个东西,即使有挂起函数,你也需要协程构建器,例如上面代码中的 asynclaunch