【问题标题】:Async Wait Efficient Execution异步等待高效执行
【发布时间】:2021-06-13 19:14:37
【问题描述】:

我需要并行迭代 100 个 id 并将结果收集到列表中。我正在尝试按照以下方式进行操作

val context = newFixedThreadPoolContext(5, "custom pool")
val list = mutableListOf<String>()
ids.map { 
  val result:Deferred<String> =  async(context) {
    getResult(it)
  }
//list.add(result.await()
}.mapNotNull(result -> list.add(result.await())

我遇到了错误

mapNotNull(result -> list.add(result.await())

因为等待方法不可用。为什么 await 在这个地方不适用?而是注释行 //list.add(result.await() 工作正常。

使用带有自定义线程池的协程并行运行此块的最佳方法是什么?

【问题讨论】:

    标签: kotlin kotlin-coroutines


    【解决方案1】:

    一般来说,你的方向是正确的:你需要创建一个Deferred 列表,然后在它们上面创建await()

    如果这正是您正在使用的代码,那么您没有从您的第一个 map { } 块返回任何内容,因此您不会像预期的那样得到 List&lt;Deferred&gt;,而是 List&lt;Unit&gt;(什么都没有)。只需删除 val result:Deferred&lt;String&gt; = - 这样您就不会将结果分配给变量,而是从 lambda 中返回它。此外,最后一行有两个语法错误:您使用了() 而不是{},并且缺少右括号。

    在这些更改之后,我相信您的代码会正常工作,但仍然很奇怪。您似乎混合了两种不同的方法来将集合转换为另一个。一种是使用像map() 这样的高阶函数,另一种是使用循环并添加到列表中。您同时使用它们。我认为以下代码应该完全符合您的需要(感谢@Joffrey 改进它):

    val list = ids.map { 
        async(context) {
            getResult(it)
        }
    }.awaitAll().filterNotNull()
    

    【讨论】:

    • 您的答案实际上得到了更好的解释。我正在删除我的。
    • 哈哈,实际上它让我发笑,这两个答案多么相似 :-D 它们是双胞胎答案,我很失望你删除了你的答案 ;-) @Joffrey
    • 是的,这很有趣,而且时间安排也很好 :D 但是由于内容非常相似,我想只保留一个答案更有意义,您的解释在这里更详细
    • 另外值得注意的是awaitAll() 会更合适,因为它比map { it.await() } 更早失败。不过,它需要在之后过滤空值。
    • 听起来是个不错的改进,我更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 2019-12-30
    • 2017-12-30
    相关资源
    最近更新 更多