我正在執行一些代碼,這些代碼涉及來自串列中元素的批量并行請求,但我正面臨一種奇怪的行為:
import kotlinx.coroutines.*
suspend fun main() {
coroutineScope {
val hello = listOf("hello", "world")
val chunks = hello.chunked(1) {
async { translate(it.first()) }
}
chunks.forEach {
print(it.await())
}
}
}
private fun translate(word: String): String {
return if(word == "hello") {
"hola"
} else {
"mundo"
}
}
它應該顯示“holamundo”,但有時這個例子會列印“mundomundo”。
我也在Kotlin Playground上提供了它。
我在這里缺少什么?
uj5u.com熱心網友回復:
這種行為的原因是里面的代碼async沒有立即運行。它只是預定的。該async塊在呼叫 lambda 之前回傳。這就是為什么it內部async塊總是指向["world"]視窗,因此最終輸出是“mundomundo”。
拿這個例子:
fun main() {
runBlocking {
var a = 1
val deferred = async {
println(a)
}
a
deferred.await()
}
}
Playground
在這個例子中,輸出將是2而不是1因為a 在asynclambda之前被處理。
編輯:正如@IR42 在評論中指出的那樣,檔案清楚地提到傳遞給轉換函式的串列變化非常快,所以如果你想異步使用它,你應該首先復制它。
val chunks = hello.chunked(1) {
val copy = it.toList()
async { translate(copy.first()) }
}
此代碼將為您提供預期的輸出。
另一個解決方案(感謝@broot)是首先計算整個分塊串列,然后將其映射到延遲串列。
val chunks = hello.chunked(1).map {
async { translate(it.first()) }
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/371514.html
上一篇:如何在Rust中將運算子鏈接到串列上?尋找相當于kotlin的代碼
下一篇:嘗試以編程方式均勻間隔網格布局
