Scala Future不会像我期望的那样运行



我想做的是使用 Future打开线程处理可以经常调用的异步任务。

但是在async task中。我还调用两个Future函数以获取来自不同数据源的信息。

我编写一个程序来模拟这种情况。

import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Success, Failure}
import scala.util.control.Breaks
import ExecutionContext.Implicits.global
object AsyncTest {

  def main(args: Array[String]) {
    try {
      println("Run...")
      aSyncTask
    } catch {
      case e => e.printStackTrace()
    }
    Thread.sleep(999999)
  }
  //dataSource1
  def getInfo1 : Future[String]  = Future{
    "A"
  }
  //dataSource2 let it wait 3 seconds...
  def getInfo2 : Future[String]  = Future{
    Thread.sleep(3000)
    "B"
  }
  def aSyncTask = Future{
    getInfo1
    getInfo2
    var result1 : String = null
    var result2 : String = null
    getInfo1.onComplete{
      case Success(value) => result1 = value
      case Failure(t) => println {
        "An error has occured: " + t.getMessage
      }
    }
    getInfo2.onComplete{
      case Success(value) => result2 = value
      case Failure(t) => println {
        "An error has occured: " + t.getMessage
      }
    }
    /*I want to wait both Future function completed then
      I can do some business logic */
    Breaks.breakable{
      while (true) {
        if (result1 != null && result2 != null)
          Breaks.break
      }
    }
    println("----------------------")
    println("result1:"+result1)
    println("result2:"+result2)
    println("----------------------")
  }
}

我编译并执行了此程序后,它一无所获。等待。

Run...

我希望我能看到输出:

Run...
----------------------
result1:A
result2:B
----------------------

所以,我在while循环中添加了一些代码进行调试。

    Breaks.breakable{
      while (true) {
        println(result1)
        println(result2)
        if (result1 != null && result2 != null)
          Breaks.break
      }
    }

然后输出:

Run...
A
null
A
null
A
null
A
null
A
null
(After 3 seconds...)
A
B
----------------------
result1:A
result2:B
----------------------

发生了什么事?我只添加两个println来查看两个变量。

为什么当我只打印时可以按照我的预期执行该程序?

Future是可以组合的,所以我会冒险并假设您想要这样的东西:

// Important to initialize them outside of for comprehension
val (f1, f2) = (getInfo1, getInfo2)
val ab: Future[(String, String)]  = 
  for {
    r1 <- f1
    r2 <- f2
  } yield (r1, r2) // Do whatever you want to do with r1 and r2
println(Await.result(ab, Duration(10000, MILLISECONDS)))

最新更新