Kotlin 协同路由作用域和异步正确的方法?
我喜欢协同例程的概念,我一直在我的android项目中使用。目前我正在开发一个JVM模块,我将把它包含在Ktor项目中,我知道Ktor支持协同例程 (查找附加的代码段) 我只是想知道这是正确的方法吗? 如何将异步与递归结合使用 你可以推荐任何能帮助我掌握更深入的co例程知识的资源都会很有帮助 提前谢谢Kotlin 协同路由作用域和异步正确的方法?,kotlin,jvm,kotlin-coroutines,Kotlin,Jvm,Kotlin Coroutines,我喜欢协同例程的概念,我一直在我的android项目中使用。目前我正在开发一个JVM模块,我将把它包含在Ktor项目中,我知道Ktor支持协同例程 (查找附加的代码段) 我只是想知道这是正确的方法吗? 如何将异步与递归结合使用 你可以推荐任何能帮助我掌握更深入的co例程知识的资源都会很有帮助 提前谢谢 override suspend fun processInstruction(args.. ): List<Any> = coroutineScope { val dataWit
override suspend fun processInstruction(args.. ): List<Any> = coroutineScope {
val dataWithFields = async{
listOfFields.fold(mutableList()){ acc,field ->
val data = someProcess(field)
val nested = processInstruction(...nestedField) // nested call
acc.addAll(data)
acc.addAll(nested)
acc
}
}
return@coroutineScope postProcessData(dataWithFields.await())
}
override suspend-fun-processInstruction(args..):List=coroutineScope{
val dataWithFields=async{
fold(mutableList()){acc,字段->
val数据=someProcess(字段)
val nested=processInstruction(…nestedField)//嵌套调用
acc.addAll(数据)
acc.addAll(嵌套)
行政协调会
}
}
return@coroutineScope后处理数据(dataWithFields.await())
}
如果要并行处理所有嵌套调用,应将每个嵌套调用包装在async
中(async
应位于循环内部)。然后,在循环之后,您应该等待所有结果。(在您的代码中,您在singleasync
之后立即运行wait
,因此没有并行执行)
例如,如果您有元素
:
interface Element {
val subElements: List<Element>
suspend fun calculateData(): SomeData
}
interface SomeData
正如您在评论部分所说,您需要父数据来计算子数据,因此
calculateAllData()
应该做的第一件事是计算父数据:
suspend fun Element.calculateAllData(
parentData: SomeData = defaultParentData()
): List<SomeData> = coroutineScope {
val data = calculateData(parentData)
val subData = subElements.map { sub -> async { sub.calculateAllData(data) } }
return@coroutineScope listOf(data) + subData.awaitAll().flatten()
}
以及以下测试:
println(measureTime {
elmOf(
elmOf(),
elmOf(
elmOf(),
elmOf(
elmOf(),
elmOf(),
elmOf()
)
),
elmOf(
elmOf(),
elmOf()
),
elmOf()
).calculateAllData()
})
如果不需要父数据来计算子数据,它将打印
1.06s
,因为在这种情况下,所有数据都是并行计算的。否则,它将打印4.15s
,因为元素树的高度是4。这非常有用。如果子数据依赖于数据(意味着我们需要父元素信息来处理子元素),那么我应该在声明val data=async{calculateData()}之后立即调用wait,正如您所指出的,将不会有并行执行。在这种情况下,什么是有效的处理方法???@TechDrago从不在async
之后立即调用wait
。这是毫无意义的。只需从val data=async{calculateData()}
中删除async
,并从data.await()
@TechDrago中删除await
,如果按照我在前面的注释中所说的做,每个元素自己的数据将在子元素数据之前计算。但是子元素数据仍然会并行计算,因为awaitAll
。嘿@Bananon如果某个数据从父计算返回一个值,我必须将该值提供给calculateData(在子元素上)。所以我不能说result.myvalue,因为它是一个延迟对象,类似这样:async{calculateData(“硬编码值”)}
subElements.map{sub->async{sub.calculatealdata(“父操作的值(网络操作假设)”)}
谢谢,你的回答帮助我更好地理解了这个概念。
class ElementImpl(override val subElements: List<Element>) : Element {
override suspend fun calculateData(parentData: SomeData): SomeData {
delay(1000)
return SomeData()
}
}
fun elmOf(vararg elements: Element) = ElementImpl(listOf(*elements))
println(measureTime {
elmOf(
elmOf(),
elmOf(
elmOf(),
elmOf(
elmOf(),
elmOf(),
elmOf()
)
),
elmOf(
elmOf(),
elmOf()
),
elmOf()
).calculateAllData()
})