【发布时间】:2018-08-07 01:37:20
【问题描述】:
我正在使用 scala (2.12) 期货对复杂问题应用并发分而治之的方法。这是一些(简化的)上下文:
def solve(list: List[Int], constraints: Con): Future[Boolean] =
Future.unit.flatMap{ _ =>
//positive case
if(list.isEmpty) Future.successful(true)
//negative case
else if(someTest(constraints)) Future.successful(false)
//divide and conquer
else {
//split to independent problems, according to constraints
val components: List[List[Int]] = split(list,constraints)
//update the constraints accordingly (heavy computation here)
val newConstr: Con = updateConstr(...)
val futureList = components.map(c => solve(c,newConstr))
allTrue(Future.successful(true), futureList)
}
}
此递归函数采用整数变量列表和代表问题约束的Con 对象,并在每次调用期间产生多个独立的子问题。
我的问题的相关部分是致电allTrue。如果我按顺序解决问题,我会写components.forall(c => solve(c,newConstr))。然而,在并发版本中,我有类似的东西
这不会在遇到第一个 false 情况时停止计算。
//async continuation passing style "forall"
def allTrue(acc: Future[Boolean], remaining: List[Future[Boolean]]):
Future[Boolean] = {
remaining match {
case Nil => acc
case r :: tail => acc.flatMap{ b =>
if(b) allTrue(r,tail)
else{
//here, it would be more efficient to stop all other Futures
Future.successful(false)
}
}
}
}
我已经阅读了多篇博客文章和论坛帖子,讨论如何停止 scala 期货通常不是一个好主意,但在这种情况下,我认为它会非常有用。
关于如何在期货列表中获得 forall 行为的任何想法?
【问题讨论】:
-
为什么是
List[Future[Boolean]]而不是Future[List[Boolean]]。如果你想转换你可以用户Future.sequence -
我不转换整个列表,因为我想独立处理每个元素:想法是,一旦一个 future 以值
false完成,我想停止所有其他计算并返回 false -
也许你可以在所有期货之间共享一个 atomicBoolean 标志。对于每个未来,如果标志说好的,那么未来可以继续进行繁重的计算部分。一旦一个future失败,则flag被设置为false(通过那个失败的future),以便其他future将跳过繁重的计算部分(如果它们没有到达检查标志的代码行)并返回false
标签: scala future divide-and-conquer