【问题标题】:Scala - Futures not startingScala - 期货没有开始
【发布时间】:2018-04-05 19:12:40
【问题描述】:

我想在一个名为 extraire_phrases 的 Future 方法上启动两个工作人员。我在我的 main 中调用它们,但似乎 Promise 从未实现,并且在我的 main 结束时我没有得到任何东西,就好像工人没有开始一样。有任何想法吗?非常感谢。

object Main {

    val chemin_corpus:String = "src/corpus.txt"
    val chemin_corpus_backup:String = "src/tartarinalpes.txt"
    val chemin_dictionnaire:String = "src/dicorimes.dmp"
    val chemin_dictionnaire_backup:String = "src/dicorimes2.dmp"

    def main(args:Array[String]){

        val quatrain = Promise[List[Phrase]]()

        var grosPoeme = List[Phrase]()

        Future {
          val texte_1 = Phrases.extraire_phrases(chemin_corpus, chemin_dictionnaire)
          val texte_2 = Phrases.extraire_phrases(chemin_corpus_backup, chemin_dictionnaire_backup)

          texte_1.onComplete {
            case Success(list) => {
              val poeme = new DeuxVers(list)
              poeme.ecrire :: grosPoeme
            }
            case Failure(ex) => {
              quatrain.failure(LameExcuse("Error: " + ex.getMessage))
            }
          }

          texte_2.onComplete {
            case Success(lst) => {
              val poeme2 = new DeuxVers(lst)
              poeme2.ecrire :: grosPoeme
            }
            case Failure(ex) => {
              quatrain.failure(LameExcuse("Error: " + ex.getMessage))
            }
          }
        quatrain.success(grosPoeme)
        }

        println(quatrain.future)
        println(grosPoeme)
    }

}

这是执行后我的控制台中的内容:

Future(<not completed>)
List()

即使我在val texte_1 之前删除了Future {,似乎它们都没有正常触发,texte_1 以某种方式启动,有时它工作,有时不工作,并且 texte_2 永远不会启动(永远不会完成)。也没有失败。

// 编辑:Alvaro Carrasco 的答案是正确的。不过谢谢你们俩的帮助

【问题讨论】:

  • 请使用答案旁边的复选标记将我的答案标记为您选择的答案(如果您确实认为是的话)。谢谢。

标签: scala concurrency


【解决方案1】:

期货是异步执行的,您的代码不会“等待”它们完成。 onComplete 将安排一些代码在未来完成时运行,但不会强制您的程序等待结果。

您需要使用map/flatMap/sequence 对内部期货进行线程化,这样您最终会得到一个单一的期货,然后使用Await.result(...) 等待它。

您实际上并不需要Promise,因为将来会捕获异常。

类似这样的:

object Main {

  val chemin_corpus:String = "src/corpus.txt"
  ...

  def main(args:Array[String]){
    ...

    val f1 = texte_1
      .map {list => 
        val poeme = new DeuxVers(list)
        poeme.ecrire :: grosPoeme
      }

    val f2 = texte_2
      .map {lst => 
        val poeme2 = new DeuxVers(lst)
        poeme2.ecrire :: grosPoeme
      }

    // combine both futures
    val all = for {
      res1 <- f1
      res2 <- f2
    } yield {
      println(...)
    }
    // wait for the combined future
    Await.result(all, 1.hour)
  }
}

【讨论】:

  • 您好,感谢您的回答。似乎虽然您的解决方案有效,但它只会启动 f2,如果我在 val all 上执行 println(grosPoeme),它什么也不会打印...啊,我敢肯定这很容易,但我就是不明白
  • @VanhaerenThomas 请记住:scala List 是不可变的。你不能改变它。 :: 构造函数为您提供了一个全新的列表。如果要使用突变,则必须使用scala.collection.mutable.ListBuffer 并调用它的append 方法。
  • 是的,它确实是不可变的。但是由于我在最后一个 val 中得到了 Future(....),我如何访问里面的内容?使用case Success(lst) 创建all.onComplete ... 似乎不起作用,即使使用case Success(lst) =&gt; println(lst) 也不会返回任何内容
  • 没关系,我找到了答案 :) 只需将 await.result 放入 val: val x = Await.result(all, 1.hour) 中,然后在列表中调用你想要的。感谢您的帮助。
【解决方案2】:

for-comprehension on Future 的解决方案。您需要更改 f1f2 才能满足您的需求。 f1f2 将并行执行。 for-comprehension 提供了获得未来结果的优雅方式(它只是 flatMapfilter 等操作组合的语法糖:

import scala.concurrent.{Await, Future}

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

val f1: Future[Seq[Int]] = Future {
  // Do something here
  Seq(1, 2, 3)
}.recover { case ex =>
    // If Future fails, let's log an exception and return default value
    println(s"Unable to complete f1: $ex")
    Seq.empty[Int]
}

val f2: Future[Seq[Int]] = Future {
  // Do something here
  Seq(4, 5, 6)
}.recover { case ex =>
  // If Future fails, let's log an exception and return default value
  println(s"Unable to complete f2: $ex")
  Seq.empty[Int]
}
// f1 and f2 have started

// we use for-comprehension on Future to get the result
val f = for {
  seq1 <- f1
  seq2 <- f2
} yield seq1 ++ seq2

// Blocking current thread and wait 1 seconds for the result
val r = Await.result(f, 1.seconds)
println(s"Result: $r")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2019-04-11
    相关资源
    最近更新 更多