cats 是否并行映射 N 运行 所有的未来?
Does cats mapN run all the futures in parallel?
如 jump-start guide 中所述,mapN 将 运行 并行处理所有未来,因此我创建了以下简单的 Scala 程序,但示例 运行 显示 diff 为 9187 毫秒,diffN 为 9106 毫秒。 所以看起来 mapN 也在按顺序 运行ning 期货,不是吗?如果我遗漏了什么请告诉我?
package example
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import java.time.LocalDateTime
import java.time.Duration
import scala.util.Failure
import scala.util.Success
import java.time.ZoneOffset
import cats.instances.future._
import cats.syntax.apply._
object FutureEx extends App {
val before = LocalDateTime.now()
val sum = for {
a <- getA
b <- getB
c <- getC
} yield (a + b + c)
sum onComplete {
case Failure(ex) => println(s"Error: ${ex.getMessage()}")
case Success(value) =>
val after = LocalDateTime.now()
println(s"before: $before")
println(s"after: $after")
val diff = getDiff(before, after)
println(s"diff: $diff")
println(s"sum: $value")
}
// let the above finish
Thread.sleep(20000)
val beforeN = LocalDateTime.now()
val usingMapN = (getA, getB, getC).mapN(add)
usingMapN onComplete {
case Failure(ex) => println(s"Error: ${ex.getMessage()}")
case Success(value) =>
val afterN = LocalDateTime.now()
println(s"beforeN: $beforeN")
println(s"afterN: $afterN")
val diff = getDiff(beforeN, afterN)
println(s"diffN: $diff")
println(s"sum: $value")
}
def getA: Future[Int] = {
println("inside A")
Thread.sleep(3000)
Future.successful(2)
}
def getB: Future[Int] = {
println("inside B")
Thread.sleep(3000)
Future.successful(3)
}
def getC: Future[Int] = {
println("inside C")
Thread.sleep(3000)
Future.successful(4)
}
def add(a: Int, b: Int, c: Int) = a + b + c
def getDiff(before: LocalDateTime, after: LocalDateTime): Long = {
Duration.between(before.toInstant(ZoneOffset.UTC), after.toInstant(ZoneOffset.UTC)).toMillis()
}
}
因为在 Future
之外还有 sleep
它应该是这样的:
def getA: Future[Int] = Future {
println("inside A")
Thread.sleep(3000)
2
}
所以你用 apply
- Future.successful
开始异步 Future
另一方面 returns 纯值,这意味着你在同一个线程中执行 sleep
。
时间快到 mapN
被调用了。
(getA, getB, getC).mapN(add)
此表达式正在创建一个元组(顺序),然后对其调用 mapN
。所以它调用 getA
然后 getB
然后 getC
因为它们每个都有 3 秒的延迟,所以需要 9 秒。
如 jump-start guide 中所述,mapN 将 运行 并行处理所有未来,因此我创建了以下简单的 Scala 程序,但示例 运行 显示 diff 为 9187 毫秒,diffN 为 9106 毫秒。 所以看起来 mapN 也在按顺序 运行ning 期货,不是吗?如果我遗漏了什么请告诉我?
package example
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import java.time.LocalDateTime
import java.time.Duration
import scala.util.Failure
import scala.util.Success
import java.time.ZoneOffset
import cats.instances.future._
import cats.syntax.apply._
object FutureEx extends App {
val before = LocalDateTime.now()
val sum = for {
a <- getA
b <- getB
c <- getC
} yield (a + b + c)
sum onComplete {
case Failure(ex) => println(s"Error: ${ex.getMessage()}")
case Success(value) =>
val after = LocalDateTime.now()
println(s"before: $before")
println(s"after: $after")
val diff = getDiff(before, after)
println(s"diff: $diff")
println(s"sum: $value")
}
// let the above finish
Thread.sleep(20000)
val beforeN = LocalDateTime.now()
val usingMapN = (getA, getB, getC).mapN(add)
usingMapN onComplete {
case Failure(ex) => println(s"Error: ${ex.getMessage()}")
case Success(value) =>
val afterN = LocalDateTime.now()
println(s"beforeN: $beforeN")
println(s"afterN: $afterN")
val diff = getDiff(beforeN, afterN)
println(s"diffN: $diff")
println(s"sum: $value")
}
def getA: Future[Int] = {
println("inside A")
Thread.sleep(3000)
Future.successful(2)
}
def getB: Future[Int] = {
println("inside B")
Thread.sleep(3000)
Future.successful(3)
}
def getC: Future[Int] = {
println("inside C")
Thread.sleep(3000)
Future.successful(4)
}
def add(a: Int, b: Int, c: Int) = a + b + c
def getDiff(before: LocalDateTime, after: LocalDateTime): Long = {
Duration.between(before.toInstant(ZoneOffset.UTC), after.toInstant(ZoneOffset.UTC)).toMillis()
}
}
因为在 Future
之外还有 sleep
它应该是这样的:
def getA: Future[Int] = Future {
println("inside A")
Thread.sleep(3000)
2
}
所以你用 apply
- Future.successful
开始异步 Future
另一方面 returns 纯值,这意味着你在同一个线程中执行 sleep
。
时间快到 mapN
被调用了。
(getA, getB, getC).mapN(add)
此表达式正在创建一个元组(顺序),然后对其调用 mapN
。所以它调用 getA
然后 getB
然后 getC
因为它们每个都有 3 秒的延迟,所以需要 9 秒。