3

我写了这个方法:

import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }
}

我期待 Future.sequence 将 List[Future] 收集到 Future[List] 中,然后等待每个期货(在我的情况下为 f1 和 f2)完成,然后再在我的情况下调用 Future[List] seq 上的 onSuccess。

但是在多次运行此代码之后,它只会偶尔打印一次“List(1, 2)”,我无法弄清楚为什么它不能按预期工作。

4

2 回答 2

5

试试这个一次,

import scala.concurrent._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  implicit val exec = ExecutionContext.fromExecutor(Executors.newCachedThreadPool)
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }
}

这将始终打印List(1,2). 原因很简单,exec上面是线程(不是守护线程)的 ExecutionContext,在您的示例中,ExecutionContext 是默认的,ExecutionContext.Implicits.global其中包含守护线程。

Hence being daemon, the process doesn't wait for seq future to be completed and terminates. if at all seq does get completed then it prints. But that doesn't happen always

于 2015-01-22T10:44:41.757 回答
2

The application is exiting before the future is completes.

You need to block until the future has completed. This can be achieved in a variety of ways, including changing the ExecutionContext, instantiating a new ThreadPool, Thread.sleep etc, or by using methods on scala.concurrent.Await

The simplest way for your code is by using Await.ready. This blocks on a future for a specified amount of time. In the modified code below, the application waits for 5 seconds before exiting.

Note also, the extra import scala.concurrent.duration so we can specify the time to wait.

import scala.concurrent._
import scala.concurrent.duration._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }

  Await.ready(seq, 5 seconds)
}

By using Await.result instead, you can skip the onSuccess method too, as it will return the resulting list to you.

Example:

val seq: List[Int] = Await.result(Future.sequence(lf), 5 seconds)
println(seq)
于 2015-01-23T09:18:11.977 回答