我想执行顺序返回期货的功能列表。
以下方法的可能实现方式是什么?
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A)
(implicit ec: ExecututionContext): Future[List[B]]
测试
test("execute futures sequentially") {
import scala.concurrent.ExecutionContext.Implicits.global
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] = ???
val l: List[Unit ⇒ Future[Unit]] = List(
_ ⇒ Future { Thread.sleep(1000); println(1) },
_ ⇒ Future { Thread.sleep(5000); println(2) },
_ ⇒ Future { Thread.sleep(500); println(3) }
)
Await.result(runSequentially(l)(5), 20.seconds)
}
应打印:
1
2
3
答案 0 :(得分:4)
尝试使用一个线程创建一个池,并像这样使用Future.traverse
val singleThreadPool = Executors.newFixedThreadPool(1, (r: Runnable) => new Thread(r, s"single-thread-pool"))
implicit val singleThreadEc = ExecutionContext.fromExecutor(singleThreadPool)
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] =
Future.traverse(lazyFutures)(f => f(input))
答案 1 :(得分:2)
def runSequentially[A, B](lazyFutures: Seq[A => Future[B]])(input: A)(implicit ctx: ExecutionContext): Future[List[B]] =
lazyFutures.foldLeft(Future.successful(List.empty[B])) { (futAcc, f) =>
futAcc.flatMap { acc =>
f(input).flatMap { result =>
result :: acc
}
}
}.map(_.reverse)
应该做到这一点(还没有测试过)。通过在列表前添加和反转,复杂度为O(n),而添加为O(n ^ 2),因为添加为O(n)并且添加完成了n次。
答案 2 :(得分:2)
您还可以使用cats
和Kleisli
import scala.concurrent.ExecutionContext.Implicits.global
import cats.implicits._
import cats.data.Kleisli
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A) : Future[List[B]] = lazyFutures
.map(Kleisli.apply) //List[Kleisli[Future, A, B]]
.sequence //Kleisli[Future, A, List[B]]
.run(input)
答案 3 :(得分:0)
这是我想出的有效的方法
def runSequentially[A, B](lazyFutures: List[A ⇒ Future[B]])(input: A): Future[List[B]] = {
lazyFutures.foldLeft(Future.successful(List.empty[B])) { (acc, curr) ⇒
for {
a ← acc
c ← curr(input)
} yield c :: a
}
}