无法理解什么是并行计算list元素的正确方法,但是阻塞主线程而不计算元素(并行)。用例:我有一个URL链接列表和一个html页面的简单解析器,我需要通过并行解析每个页面来减少从给定页面获取信息所需的时间,然后用一些JSON数据返回一个简单的列表。
据我所知,我有两个选择:
并发方式与期货
我有一种方法可以在将来提取一些JSON数据:
def extractData(link: String): Future[JValue] = // some implementation我只需将其映射到链接列表上,其中的类型是List[FutureJValue]:
val res: List[Future[JValue]] = listOfLink.map(extractData)如果我调用sequence (例如从Scalaz或我自己的实现)遍历这个列表并将其转换为Future[List[JValue]],那么链接仍将按顺序处理,但是一个单独的线程,这不会给我任何效率,因为结果我需要得到一个List[JValue]。
尝试使用ParSeq进行计算
在这个选项中,我有一个函数,它只提取数据:
def extractData(link: String): JValue = // some implementation但是这次调用集合上的.par:
val res: ParSeq[JValue] = listOfLinks.map(extractData)但在这种情况下,我不太明白如何阻塞主线程,而不按顺序解析每个链接,就无法计算孔列表。
至于阿克卡,我只是不能在这里使用演员,所以只有Future或Par*
发布于 2013-08-14 17:39:41
当您在集合上映射extractData时,这些链接将并行处理。考虑一个稍微简化的例子:
import scala.concurrent._
import ExecutionContext.Implicits.global
def extractData(s: String) = future {
printf("Starting: %s\n", s)
val i = s.toInt
printf("Done: %s\n", s)
i
}
val xs = (0 to 5).map(_.toString).toList
val parsed = Future.sequence(xs map extractData)现在,您将看到如下内容,它清楚地表明,这些事情不是按顺序处理的:
Starting: 0
Done: 0
Starting: 2
Done: 2
Starting: 1
Starting: 4
Done: 1
Starting: 3
Starting: 5
Done: 5
Done: 4
Done: 3请注意,您可以使用Future.traverse来避免创建期货的中间列表:
val parsed = Future.traverse(xs)(extractData)在这两种情况下,您都可以使用Await阻止
val res = Await.result(parsed, duration.Duration.Inf)作为脚注:我不知道您是否计划使用Dispatch来执行HTTP请求,但如果没有,则值得一看。它还提供了集成良好的JSON解析,文档中充满了如何使用未来的有用示例。
https://stackoverflow.com/questions/18238078
复制相似问题