第一次for-callback几乎每次都会打印将来的列表,第二ononComplete-callback很少返回成功(从不失败)

时间:2019-06-06 08:08:55

标签: scala concurrency callback future

我正在看一些未来的例子。我有一个Future从方法中检索列表。我调用两种不同的回调,一个Foreach回调和一个onComplete回调只是为了尝试它们。

  • Foreach回调几乎每次都返回列表。
  • 即使For回调已返回列表,onComplete回调也很少返回SUCCESS。
  • onComplete回调永远不会返回FAILURE。

有人可以向我解释发生了什么吗?

我知道回调确实是并发执行的,并且没有命令。但是,如果Future将列表返回给Foreach并且在Foreach和Future之前执行了onComplete回调,并且它试图从失败的Future中获取列表,那么onComplete回调不应该返回FAILURE吗?

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object FuturesExampleObj extends App {

  println("Using Future to retrieve list\n")
  val l: Future[List[String]] = Future {
    getList()
  }

  println("FOR CALLBACK --------------------\n")

  l foreach {
    items =>
      for(item <- items) println(s"foreach item : $item")
      println("\n")
  }

  println("onComplete CALLBACK --------------------\n")

  l onComplete {
    case Success(i) => println(s"SUCCESS : $i")
    case Failure(i) => println(s"FAILURE : $i")
  }

  def getList(): List[String] ={
    val list = ("a" :: "b" :: "c" :: "d" :: "e":: Nil)
    list
  }
}

结果示例1(通用)

Using Future to retrieve list

FOR CALLBACK --------------------

onComplete CALLBACK --------------------

foreach item : a
foreach item : b
foreach item : c
foreach item : d
foreach item : e



Process finished with exit code 0

结果示例2(罕见)

Using Future to retrieve list

FOR CALLBACK --------------------

onComplete CALLBACK --------------------


Process finished with exit code 0

结果示例3(非常少见)

基本上onComplete永远不会返回SUCCESS或FAILURE。有时,很少会返回“ SUCCESS:” +列表。

2 个答案:

答案 0 :(得分:2)

这是因为您必须明确阻止未来。 对于您来说,主线程在onComplete完成之前终止,有时在l foreach ..完成之前终止。

请添加:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

val listF = l foreach {
  items =>
    for(item <- items) println(s"foreach item : $item")
    println("\n")
}

Await.result(listF, 5 seconds)

那样,您将等待这个未来的完成。

如果要等待onComplete,则需要使用Thread.sleep(将其添加到onComplete之后,例如:

l onComplete {
   case Success(i) => println(s"SUCCESS : $i")
   case Failure(i) => println(s"FAILURE : $i")
}

Thread.sleep(3000)

onComplete在ExecutionContext中的某个线程上运行,而Await在当前线程上运行,并阻塞它直到完成或超过指定的超时。 因此onComplete是非阻塞的,而Await是阻塞的。

使用onComplete时,我们不会阻止Future的结果,而是会收到SuccessFailure的回调。

Thread.sleep()正在阻塞我们的主线程,以便我们可以看到将来的异步结果。

请注意,您不应在生产代码中使用Await.result,它用于测试Future的输出。 此外,您肯定不会使用Thread.sleep(),而是会对将来返回的结果“做出反应”。

通常,您将有一些REST API调用或另一项服务正在运行,并等待将来完成。

答案 1 :(得分:1)

原因是应用程序的线程在Future完成之前完成。

只需在程序的和处添加Await.ready(l, Duration.Inf).value.get

仅用于测试!