簡體   English   中英

為什么Scala的Future.onComplete需要一個ExecutionContext

[英]Why does Scala's Future.onComplete needs an ExecutionContext

Promise.complete不能只運行Future.onComplete的回調,而不能一直通過ExecutionContext並且據我所知,不能安排Future.onComplete的回調用於以后並可能在另一個線程中運行嗎?

您可以向onComplete提供自己的ExecutionContext ,它將在同一線程上運行代碼:

val immediateContext: ExecutionContext = new ExecutionContext {
  def execute(runnable: Runnable) {
    runnable.run()
  }
  def reportFailure(cause: Throwable) {}
}

您甚至可以將其設為implicit ,並且對於希望在另一個線程中執行的情況,可以提供scala.concurrent.ExecutionContext.global或其他上下文。

這是一個測試,它如何工作:

val immediateContext: ExecutionContext = new ExecutionContext {
  override def reportFailure(cause: Throwable): Unit = {}
  override def execute(runnable: Runnable): Unit = {
    println("Executing")
    runnable.run()
    println("Executed")
  }
}

def testContext(): Unit = {
  println("Scheduling on an uncompleted future")
  val p = Promise[Int]()
  println("Scheduling")
  p.future.onComplete { _ => println("Completed") }(immediateContext)
  println("Scheduled")
  p.complete(Success(5))

  println()

  println("Scheduling on an already completed future")
  val p2 = Promise[Int]().complete(Success(5))
  println("Scheduling")
  p2.future.map { n =>
    println("Mapping")
    n * 2
  }(immediateContext).onComplete{
    case Success(n) => println(s"Completed: $n") 
    case _ =>
  }(immediateContext)
  println("Scheduled")

  println()

  println("Using scala.concurrent.ExecutionContext.global for comparison")
  val p3 = Promise[Int]().complete(Success(5))
  println("Scheduling")
  p3.future.onComplete {
    _ => println("Completed")
  }(concurrent.ExecutionContext.global)
  println("Scheduled")
}

運行testContext()將打印

Scheduling on an uncompleted future
Scheduling
Scheduled
Executing
Completed
Executed

Scheduling on an already completed future
Scheduling
Executing
Mapping
Executed
Executing
Completed: 10
Executed
Scheduled

Using scala.concurrent.ExecutionContext.global for comparison
Scheduling
Scheduled
Completed

這是實現scala Futures的設計決策,所有操作(地圖,flatMap等)都需要隱式的ExecutionContext。

如果您想擁有更好的線程可重用性,並且線程之間的上下文切換更少,我建議您看一下scalaz Task,它對於延遲計算的抽象略有不同: http ://timperrett.com/2014/07/20/ scalaz-task-missing文檔/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM