Scala Future.find
Scala 2.12有2个Scala Future.find,scala,future,scala-2.12,Scala,Future,Scala 2.12,Scala 2.12有2个未来。查找方法 @deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12.0") def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predi
未来。查找方法
@deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12.0")
def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predicate) p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]]
以及它的重载版本
def find[T](futures: scala.collection.immutable.Iterable[Future[T]])(p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]]
两者的描述相同
因此,我假设这些方法在给定的列表中找到与paramp
匹配的第一个完成的Future
但实际上只有第一个是这样做的
val start = System.currentTimeMillis
val a = (1 to 3).reverse.iterator.map{ x =>
Future{
Thread.sleep(x * 10000)
x
}
}
val b = Future.find(a)(_.isInstanceOf[Int])
b.foreach{ x =>
println(x)
println(System.currentTimeMillis - start) // 10020
}
该方法的不推荐版本返回最快的版本
val a = (1 to 3).reverse.map{ x =>
Future{
Thread.sleep(x * 10000)
x
}
}
val b = Future.find(a)(_.isInstanceOf[Int])
b.foreach{ x =>
println(x)
println(System.currentTimeMillis - start)
}
重载版本返回最慢的版本。更准确地说,它只是从头到尾检查给定的列表,而不在乎完成这些列表需要多长时间
应该是这样的吗?如果是这样的话,使用复制的还是自己实现它是唯一关心它们的完成时间的选项?您是对的,在2.12.x中期望一次可遍历的[Future[T]
与替换Future.find的行为不同。正如您从下面粘贴的源代码中看到的,前一种find
方法利用Promise
和tryComplete
有效地从输入集合捕获第一个完成的未来,而后一种方法使用一个简单的hasNext/next
遍历:
@deprecated("use the overloaded version of this method that takes a scala.collection.immutable.Iterable instead", "2.12.0")
def find[T](@deprecatedName('futurestravonce) futures: TraversableOnce[Future[T]])(@deprecatedName('predicate) p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = {
val futuresBuffer = futures.toBuffer
if (futuresBuffer.isEmpty) successful[Option[T]](None)
else {
val result = Promise[Option[T]]()
val ref = new AtomicInteger(futuresBuffer.size)
val search: Try[T] => Unit = v => try {
v match {
case Success(r) if p(r) => result tryComplete Success(Some(r))
case _ =>
}
} finally {
if (ref.decrementAndGet == 0) {
result tryComplete Success(None)
}
}
futuresBuffer.foreach(_ onComplete search)
result.future
}
}
def find[T](futures: scala.collection.immutable.Iterable[Future[T]])(p: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = {
def searchNext(i: Iterator[Future[T]]): Future[Option[T]] =
if (!i.hasNext) successful[Option[T]](None)
else {
i.next().transformWith {
case Success(r) if p(r) => successful(Some(r))
case other => searchNext(i)
}
}
searchNext(futures.iterator)
}
实现您自己的方法之一可能是将带有添加谓词的Future.firstCompletedOf
方法扩展为如下内容:
def firstConditionallyCompletedOf[T](futures: List[Future[T]])(p: T => Boolean)(implicit ec: ExecutionContext): Future[T] = {
val p = Promise[T]()
val firstCompleteHandler = new AtomicReference[Promise[T]](p) with (Try[T] => Unit) {
override def apply(v1: Try[T]): Unit = getAndSet(null) match {
case null => ()
case some => some tryComplete v1
}
}
futures.foreach{ _.filter(condition).onComplete(firstCompleteHandler) }
p.future
}
你说的“最慢的”或“最快的”是什么意思?在第二个例子中,因为a
是一个迭代器;它将被val c=Future.firstCompletedOf(a)
和val b=Future.find(a)([Int])
将获得一个空的迭代器@SarveshKumarSingh删除该行。这是某种复制粘贴错误
def firstConditionallyCompletedOf[T](futures: List[Future[T]])(p: T => Boolean)(implicit ec: ExecutionContext): Future[T] = {
val p = Promise[T]()
val firstCompleteHandler = new AtomicReference[Promise[T]](p) with (Try[T] => Unit) {
override def apply(v1: Try[T]): Unit = getAndSet(null) match {
case null => ()
case some => some tryComplete v1
}
}
futures.foreach{ _.filter(condition).onComplete(firstCompleteHandler) }
p.future
}