Scala Future的地图是否会增加任何开销?

时间:2017-12-24 13:30:35

标签: scala concurrency future

假设我有这样的功能:

import scala.concurrent._

def plus2Future(fut: Future[Int])
               (implicit ec: ExecutionContext): Future[Int] = fut.map(_ + 2)

现在我正在使用plus2Future创建新的Future

import import scala.concurrent.ExecutionContext.Implicits.global
val fut1 = Future { 0 }
val fut2 = plus2Future(fut1)

函数plus2 是否始终现在在与fut1相同的线程上运行?我猜它没有。
 在map中使用plus2Future是否会增加线程上下文切换的开销,创建新的Runnable等?

2 个答案:

答案 0 :(得分:2)

  

在plus2Future中使用map会增加线程上下文的开销   切换,创建一个新的Runnable等?

map,关于Future的默认实施(通过DefaultPromise)是:

def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity)
  val p = Promise[S]()
  onComplete { v => p complete (v map f) }
  p.future
}

onComplete创建新CallableRunnable并最终调用dispatchOrAddCallback的位置:

/** Tries to add the callback, if already completed, it dispatches the callback to be executed.
 *  Used by `onComplete()` to add callbacks to a promise and by `link()` to transfer callbacks
 *  to the root promise when linking two promises togehter.
 */
@tailrec
private def dispatchOrAddCallback(runnable: CallbackRunnable[T]): Unit = {
  getState match {
    case r: Try[_]          => runnable.executeWithValue(r.asInstanceOf[Try[T]])
    case _: DefaultPromise[_] => compressedRoot().dispatchOrAddCallback(runnable)
    case listeners: List[_] => if (updateState(listeners, runnable :: listeners)) () else dispatchOrAddCallback(runnable)
  }
}

将调用分派给底层执行上下文。这意味着由实施ExecutionContext来决定未来的运行方式和地点,因此无法给出确定性答案"它在这里或那里运行"。我们可以看到存在Promise和回调对象的分配。

一般情况下,除非我对代码进行基准测试并发现这是一个瓶颈,否则我不会担心这一点。

答案 1 :(得分:1)

不,它不能(确定地)使用相同的线程(除非EC只有一个线程),因为在两行代码之间可以经过无限的时间。