Возможная ошибка в Scala 2.10: фьючерсы не запускать

Я пытался воспроизвести пример на новом Scala 2.10 фьючерсы характеристика. Код, который я использовал:

import scala.concurrent.Future
import scala.concurrent.future

object Test {
    def main(args: Array[String]) {
     println("Test print before future")
     val s = "Hello"
     val f = future {s + " future!"}
     f onSuccess {case v => println(v)}
     println("Test print after future")
    }
}

вместо печатания:

Test print before future
Hello future!
Test print after future

Он просто печатает:

Test print before future
Test print after future

есть идеи, почему у меня такое поведение? Моя версия компилятора scala-2.10.0-20120507.

3 ответов


проблема в том, что вы выполняете это как автономную программу, основной поток которой завершается, прежде чем один из рабочих потоков сможет выполнить "Hello future!"println. (Потоки, которые порождает новая библиотека фьючерсов, являются потоками демонов).

вы также можете использовать обратите внимание, что при использовании Await, ты загораживаешь. Это, конечно, имеет смысл, чтобы убедиться, что ваш основной поток приложения не завершается, но обычно не должен использоваться, если не требуется иначе.

(том Await объект является необходимым аварийным люком для таких ситуаций, но использование его во всем коде приложения без учета его семантики может привести к более медленному, менее параллельному выполнению. Если вам нужно убедиться, что обратные вызовы выполняются в определенном порядке, например, существуют другие альтернативы, такие как andThen и map методы Future.)


Я думаю, что проблема здесь-это время. Скорее всего, ваш будущий код работает в отдельном потоке deamon. Я думаю, что приложение заканчивается очень быстро, и у этого потока deamon недостаточно времени для правильного выполнения (приложение не ждет завершения потоков deamon). Но это также очень системно-зависимое поведение. Для меня это печатает:

Test print before future
Test print after future
Hello future!

и затем выходит (я использую Scala 2.10.0-M3). Вы можете попробовать следовать, чтобы проверить его - просто поместите основной поток выполнения в поспите несколько секунд и посмотрите, есть ли Hello future! напечатано:

import scala.concurrent.Future
import scala.concurrent.future

object Test {
    def main(args: Array[String]) {
        println("Test print before future")

        val s = "Hello"
        val f = future {s + " future!"}
        f onSuccess {case v => println(v)}

        println("Test print after future")

        Thread.sleep(3000) 
        println("Test print at the end.")
    }
}

Я просто хочу добавить, что в целом существует еще одна возможность того, что фьючерсы не работают: достижение предела пула потоков.

в вашем случае это, вероятно, была просто проблема времени, как указывали другие, но в качестве будущей ссылки рассмотрим этот пример:

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration


object FutureDebug {
  def main( args: Array[String] ) {

    for (i <- Range(0, 4)) {
      future {
        while (true) {
          Thread.sleep(1000)
          println("I'm doing stupid things in a future")
        }
      }
    }

    println("(1) reached? yes")
    val fut = future {
      for (i <- Range(0, 1000)) {
        println("never reached " + i)
      }
      3.14
    }    
    println("(2) reached? yes")
    Await.result(fut, Duration.Inf)
    println("(3) reached? no")
  }
}

на моей машине глобальный контекст выполнения по умолчанию имеет только 4 потока. Поскольку рабочие потоки заняты выполнением 4 фьючерсов без смысла, будущее ниже никогда не будет выполняться. Вот почему следует быть осторожным с контекстом выполнения по умолчанию, и лучше всего укажите собственный контекст выполнения при работе с несколькими (действительно) долгосрочными фьючерсами.