【问题标题】:Implementing a real "forall" on a list of scala futures在 scala 期货列表上实现真正的“forall”
【发布时间】: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


【解决方案1】:

不停止期货的简单方法是Future.traverse

val all:Future[List[Boolean]] = Future.traverse(components)(c => solve(c, newConstr)
val forAll:Future[Boolean] = all.map(_.forall(identity))

对于可取消的期货列表,我建议查看 Observable 模式。在您的情况下,订阅者可以在看到 False 值后立即取消订阅,并且当没有订阅者收听时,生产者将停止计算

【讨论】:

  • 感谢traverse 的提示!关于观察者模式,我不确定我是否理解.. Future 不应该是这个模式的包装器吗?
  • Future 是一个异步值,而 Observable 是一个异步值流。看看reactivex介绍reactivex.io/intro.html
  • 好吧,我不明白你现在的意思。感谢您的有趣想法,我还没有玩过响应式编程,但我会尝试。
猜你喜欢
  • 2021-03-02
  • 1970-01-01
  • 2014-12-30
  • 2013-11-29
  • 2013-01-15
  • 2015-06-03
  • 2020-06-12
  • 2016-04-05
相关资源
最近更新 更多