我发现了一个类似的问题,但它似乎是一个更简单的情况,其中昂贵的操作总是相同的。在我的例子中,我想收集一些昂贵的API调用的一组结果,我想并行执行。
假设我有:
def apiRequest1(q: Query): Option[Result]
def apiRequest2(q: Query): Option[Result]
,其中q
是相同的值。
我想要一个List[Result]
或类似的(显然List[Option[Result]]
是好的),我想要两个昂贵的操作并行发生。
一个简单的List
构造函数自然不会并行执行:
List(apiRequest1(q), apiRequest2(q))
并行集合有帮助吗?或者我应该把目光投向未来之类的东西?我能想到的使用并行集合的唯一方法似乎很蹩脚:
List(q, q).par.zipWithIndex.flatMap((q) =>
if (q._2 % 2 == 0) apiRequest1(q._1) else apiRequest2(q._1)
)
实际上,在所有条件都相同的情况下,也许这并不是那么糟糕…
你为什么不写
List(apiRequest1 _, apiRequest2 _).par.map(_(q))
快速解决方案:
scala> def apiRequest1(q: Query): Option[Result] = { Thread.sleep(1000); Some(new Result) }
apiRequest1: (q: Query)Option[Result]
scala> def apiRequest2(q: Query): Option[Result] = { Thread.sleep(3000); Some(new Result) }
apiRequest2: (q: Query)Option[Result]
scala> val f = List(() => apiRequest1(q), () => apiRequest2(q)).par.map(_())
f: scala.collection.parallel.immutable.ParSeq[Option[Result]] = ParVector(Some(Result@1f24908), Some(Result@198c0b5))
我不确定它会并行工作如果你只有两个或一个小数量的电话,有一个并行阈值,它可能工作顺序与这么小一个集合,在地面上,这是不值得的并行开销(它可以不知道,这取决于你想要的操作,但它是合理的有一个阈值集操作)。