cats 是否并行映射 N 运行 所有的未来?

Does cats mapN run all the futures in parallel?

jump-start guide 中所述,mapN 将 运行 并行处理所有未来,因此我创建了以下简单的 Scala 程序,但示例 运行 显示 diff9187 毫秒diffN9106 毫秒所以看起来 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 秒。