Scala:映射一个id列表,为每个ID启动未来

时间:2014-05-14 23:02:08

标签: scala future

我在Scala中有一个id列表,对于每个id,我启动了一个未来来执行数据库操作,如下所示:

import myPackage.myExecutionContext

def doDbOperation(ids: List[Long]) = ids.map { id =>
  Future(get(id))
}

我注意到Futures只在列表遍历完成后执行(List非常大)。如何在不等待遍历完成的情况下尽可能地启动Future(基于可用线程)?

2 个答案:

答案 0 :(得分:4)

看看Future.traverse。文档说“这对于执行并行映射很有用。例如,将函数并行应用于列表的所有项”。

Future.traverse(ids)(id => Future(get(id)))

答案 1 :(得分:1)

我无法解释观察到的行为(在地图遍历完成之前,未来的主体不会执行)。以下内容将打印Running future while mapping

package org.example

import scala.concurrent.{ Future }
import scala.concurrent.ExecutionContext.Implicits.global

object Test extends App {

  @volatile var hasStarted = false

  val ids: List[Long] = Range.Long(0L, 100000L, 1L).toList

  val res = ids.map({ id =>
    val res = Future {
      if (!hasStarted) hasStarted = true
      id
    }
    if (hasStarted) println("Running future while mapping")
    res
  })
}

哪个有意义; Future.apply的效果不同,具体取决于是在map还是Future.traverse内调用。

Re:Future.traverse返回类型不同。

ids.map { id => Future(get(id)) }返回List[Future[DBObject]]

但是

Future.traverse(ids)(id => Future(get(id)))返回Future[List[DBObject]]

Future[List[DBObject]]几乎总是更有用,但你正在改变语义(也许你不想这样做)。