如何顺序执行scala期货列表

时间:2019-06-21 17:42:05

标签: scala future

我想执行顺序返回期货的功能列表。

以下方法的可能实现方式是什么?

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

4 个答案:

答案 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)

您还可以使用catsKleisli

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
      }
    }