试图使期货顺序执行。怎么了?

时间:2020-05-31 13:41:28

标签: scala futuretask

我正在尝试执行按顺序返回Future的功能

所以,我有一个收藏集

  val in = Seq(1, 1, -1, -2, 3, -4, 5, 6, 7, -1, -2, -9, 1, 2, 2)

和处理该集合中每个int的函数

  def intToFuture(int: Int): Future[Int] = {
    Future {
      println(s"Running function $int")
      Thread.sleep(1500)
      int * 100
    }
  }

我需要实现逻辑,该逻辑按部分并行处理来处理收集。 获取前n个元素,将每个元素并行乘以100,然后获取后n个元素并执行相同的操作...等等。

我所做的(在阅读了本网站的一些帖子之后)是,我实现了两个功能

1)处理一批计算

  def processBatch(ints: Seq[Int])(f: Int => Future[Int]): Future[Seq[Int]] = {
    Future.sequence(ints.map(f))
  }

2)和第二个,适用于迭代处理

  def batchTraverse(in: Seq[Int], size: Int)(f: Int => Future[Int]): Future[Seq[Int]] = {
    val grs = in.grouped(size).toList
    def loop(l: Seq[Seq[Int]]): Future[Seq[Int]] = {
      l match {
        case Nil =>
          Future.successful(l.flatten)//? flatten
        case head :: tail =>
          println("head="+head)
          processBatch(head)(f).flatMap{
            s => loop(tail).map{ t =>
              s.appendedAll(t)
            }
          }
      }
    }
    loop(grs)
  }

然后以

开始
  val fs: Future[Seq[Int]] = batchTraverse(in, 3)(intToFuture)

  fs.onComplete{
    f => println(f)
  }

结果是,它仅进行一次迭代,我在哪里弄错了?

1 个答案:

答案 0 :(得分:4)

您的函数实际上似乎运行良好,可能发生的情况是您的程序在将来有机会完成之前终止,因此您只看到第一个迭代。通过在代码中添加一个await,我可以使事情工作。

import scala.concurrent._
import scala.concurrent.duration._

val fs: Future[Seq[Int]] = batchTraverse(in, 3)(intToFuture)

fs.onComplete{
  f => println(f)
}

Await.result(fs, Duration.Inf)

您可能想要的持续时间小于Duration.Inf,因为它将永远等待未来的完成。这样做,我可以得到以下输出:

head=List(1, 1, -1)
Running function 1
Running function 1
Running function -1
head=List(-2, 3, -4)
Running function -4
Running function 3
Running function -2
head=List(5, 6, 7)
Running function 7
Running function 6
Running function 5
head=List(-1, -2, -9)
Running function -9
Running function -2
Running function -1
head=List(1, 2, 2)
Running function 2
Running function 2
Running function 1
Success(List(100, 100, -100, -200, 300, -400, 500, 600, 700, -100, -200, -900, 100, 200, 200))