问题
Let's say I have a function func1
that needs to return a Future
with two integers. Each of the two values are returned by independent futures, like so:
def f1 = Future { 1 }
def f2 = Future { 2 }
def func1 : Future[(Int,Int)] = {
val future1 = f1
future1.map { result1 =>
result1 * 10
}
val future2 = f2
future2.map { result2 =>
result2 * 20
}
}
I need future1
wait until future2
ends (or vice versa) to return both results as (Int,Int)
. How can this be accomplished?
回答1:
That's precisely what the zip
method on futures does:
val futurePair: Future[(Int, Int)] = future1.zip(future2)
Note that if you haven't instantiated your futures before (say, if future1
and future2
are def
s, not val
s), this will run the two computations in parallel, while a for comprehension (or flatMap
) would wait for the first one to succeed before starting the second one.
回答2:
A for
-comprehension is the best option here:
scala> import scala.concurrent.Future
import scala.concurrent.Future
scala> import concurrent.ExecutionContext.Implicits.global
import concurrent.ExecutionContext.Implicits.global
scala> def f1 = Future{1}
f1: scala.concurrent.Future[Int]
scala> def f2 = Future{2}
f2: scala.concurrent.Future[Int]
scala> for {result1 <- f1; result2 <- f2} yield (result1 * 10, result2 * 20)
res0: scala.concurrent.Future[(Int, Int)] = scala.concurrent.impl.Promise$DefaultPromise@71f67a79
More information can be found here and here.
Note: this will run the two Future
s in sequence while Cyrille Corpet's solution will run them in parallel.
回答3:
You can use a for-comprehension for futures that have already started like this:
val f1: Future[Int] = ???
val f2: Future[Int] = ???
val f3: Future[Int] = ???
val futureInts: Future[(Int, Int, Int)] = for {
result1 <- f1
result2 <- f2
result3 <- f3
} yield (result1, result2, result3)
If the futures were assigned to lazy val
s or defs
then this wouldn't work, because the futures would not have been started (if you start the futures inside the for comprehension, then they will be executed sequentially). Here is an example of starting them, and then waiting for them with for
.
Example:
val f1: Future[Int] = Future {
println("starting f1")
Thread.sleep(1000)
1
}
val f2: Future[Int] = Future {
println("starting f2")
Thread.sleep(3000)
2
}
val f3: Future[Int] = Future {
println("starting f3")
Thread.sleep(2000)
3
}
val futureInts: Future[(Int, Int, Int)] = for {
result1 <- f1
result2 <- f2
result3 <- f3
} yield (result1, result2, result3)
futureInts.map {
case tuple => println(tuple)
}
Output:
starting f1 // These first
starting f3 // threes statements
starting f2 // happen right away.
(1,2,2) // Then this prints a three seconds later
In your case you could do this:
def func1 : Future[(Int,Int)] = {
// Start futures
val future1 = f1.map(_ * 10)
val future2 = f2.map(_ * 20)
// Wait for both futures, and return a tuple
for {
result1 <- future1
result2 <- future2
} yield (result1, result2)
}
来源:https://stackoverflow.com/questions/43790952/waiting-for-another-future-to-end-to-return-a-function