0

I am learning Scala Future with the following code:

object DangerousAndSlowService {
    def queryNextNumber: Long = {
        50
    }
}

val number1F = Future { DangerousAndSlowService.queryNextNumber }

number1F.onComplete({
    case Success(value) => {
        println(s"Got the callback, meaning = $value")
    }
    case Failure(exception) => {
        exception.printStackTrace
    }
})

However, the "50" is never printed. Already spent several hours but still cannot figure it out.

Thanks.

Che-Hao Kang
  • 133
  • 1
  • 7
  • Where is this code run from? From inside a main method? – Simon Apr 06 '18 at 13:42
  • You need to wait for the result (block current thread). Check this answer, you can apply the same for your example: https://stackoverflow.com/a/49680248/5794617 – Artavazd Balayan Apr 06 '18 at 13:43
  • Not exactly duplicate of ["How do I wait for a Scala future's onSuccess callback to complete?"](https://stackoverflow.com/questions/34808024/how-do-i-wait-for-a-scala-futures-onsuccess-callback-to-complete), the problem there was an additional `Thread.sleep`. – Andrey Tyukin Apr 06 '18 at 13:48
  • It's woth noting that, blocking is only needed if the program actually might terminate before running your `Future`. If this code is run e.g. inside a Play application, the `Future` should run even if you don't block and wait for it – Simon Apr 06 '18 at 13:54

1 Answers1

4

The main thread exits without letting the future finish its job, therefore the output is non-deterministic: sometimes it does print something, sometimes it doesn't. If you don't mind blocking the main thread, you can use Await:

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

object DangerousAndSlowService {
    def queryNextNumber: Long = {
        50
    }
}

val number1F = Future { DangerousAndSlowService.queryNextNumber }

number1F.onComplete({
    case Success(value) => {
        println(s"Got the callback, meaning = $value")
    }
    case Failure(exception) => {
        exception.printStackTrace
    }
})

Await.result(number1F, 1.second)

While Await is necessary here to produce the output, it's also good to note you should use it with caution. It blocks the current thread, which is typically not what you want when you work with asynchronous computations and futures.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • @JordanCuttler "bad" sounded a bit too judgemental. If you have composed your gigantic program from thousand asynchronous computations, in the end of the day you have to launch it and await the result. You shouldn't block computations of intermediate results willy-nilly, that's true, but I wouldn't generally call `Await` "bad". – Andrey Tyukin Apr 06 '18 at 13:54
  • @Felix In what sense is it not a good solution. Can you give an example where it does not give the desired result? – Andrey Tyukin Apr 06 '18 at 15:23
  • 1
    @Felix Have you somehow confused your question with this thread? I've explicitly stated that [your question](https://stackoverflow.com/questions/49695800/scala-how-to-wait-until-future-is-complete?noredirect=1#comment86404950_49695800) is **NOT** a duplicate of this question, so that your question doesn't get closed as duplicate. You can't just go into an unrelated thread for another question and downvote everything just because it doesn't answer your particular question. – Andrey Tyukin Apr 06 '18 at 15:32
  • ah sorry didn't got this – Felix Apr 06 '18 at 15:32
  • 1
    @Felix I've included a more explicit disclaimer that this solution blocks the main thread. I didn't claim that this is appropriate for all situations (especially not in asynchronous frameworks like Play or Akka), but sometimes there is no other way. – Andrey Tyukin Apr 06 '18 at 16:22
  • Thanks for adding this information! I voted up your answer! Best regards – Felix Apr 08 '18 at 07:07
  • @AndreyTyukin Thanks for your answer. Now I know it is necessary to await the thread to finish to see the result. – Che-Hao Kang Apr 08 '18 at 15:14
  • @Che-HaoKang The comments of Felix (who came from another thread) actually point out something quite important: if you are working with asynchronous frameworks like Akka or Play, you often don't have to block anywhere. As a trade-off, the shutdown procedure becomes more complex. It depends on the context; SO-usage remark: If one of the provided answers solves your problem, you can mark your question as solved by [accepting an answer](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa). – Andrey Tyukin Apr 08 '18 at 15:31