Scala期货是否支持无阻塞组合器,例如firstNCompletedOf和firstNSuccCompletedOf?

时间:2018-09-19 14:51:09

标签: scala future

例如,Folly支持无阻塞组合器collectN,可以在https://github.com/facebook/folly/blob/master/folly/futures/helpers.h

中找到它

它没有提供一个非阻塞组合器collectNWithoutException,该组合器只会收集与collectAny类似的成功期货,但会收集多个以上的期货。

Scala似乎只提供firstCompletedOf,其中n == 1时将被collectN。

如果Scala不支持它们,如何轻松实现这些非阻塞组合器? 我想使用现有的组合器来实现。

2 个答案:

答案 0 :(得分:2)

这对于大量的期货来说是不切实际的,而是对可用组合器的演示

  def firstNCompleted[T](n: Int, futures: List[Future[T]])(implicit executor: ExecutionContext): Future[List[T]] =
    Future.firstCompletedOf(futures.combinations(n).map(Future.sequence(_)))
  • 创建n个期货Iterator[List[Future[T]]]的所有组合
  • 将每个组合排序到结果列表Iterator[Future[List[T]]]的Future中
  • 返回第一个完成的Future[List[T]]

答案 1 :(得分:1)

这里是collectN

def collectN[T](n: Int, futures: List[Future[T]]): Future[List[T]] =  {
  val promise = Promise[List[T]]
  var result:List[T] = Nil
  futures.foreach {
     _.onComplete { 
       case _ if result.length >= n => 
       case Success(t) => synchronized {            
         result = t :: result
         if(result.length == n) promise.success(result.reversed.take(n))          
       }
       case Failure(x) => promise.failure(x) 
     }
  }
  promise.future
}

请注意,如果输入期货的数量少于n(并且全部成功),它将返回一个Future,它将永远不会完成。 您可以对其进行微不足道的修改,以使其一直等到N次成功,而不是在第一次失败后中止,但是如果少于N次的期货最终成功,那也将永远等待。为避免这种情况,您可以计算已经完成的数目,并在达到原始列表的大小后退出。