2015-01-26 21 views
13

Wykonując ten kod scala, nie mam żadnych danych wyjściowych w konsoli. (Naprawdę nie rozumiem, co się dzieje)Korzystanie z futures i Thread.sleep

Jeśli usuniemy Console.println("Console.println OK!") => wszystko wydaje się być w porządku.

Jeśli usuniemy Thread.sleep(2000) => wszystko wydaje się być w porządku.

Czy masz jakieś pomysły na ten temat? Dziękuję Ci bardzo!

Clément

import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
import scala.concurrent.{Await, Future} 
import scala.language.postfixOps 

object ScalaFuture { 

    def main(args: Array[String]) { 

    val f: Future[String] = Future { 
     Thread.sleep(2000) 
     "future value" 
    } 

    f.onSuccess { 
     case s => { 
     Console.println("Console.println OK!") 
     System.out.println("System.out.println OK!") 
     } 
    } 

    Await.ready(f, 60 seconds) 
    } 

} 
+0

Działa dobrze dla mnie. Co stanie się, jeśli będziesz spać przez kilka sekund po "Await.ready"? –

+0

Jeśli śpię kilka sekund po "Await.ready' to działa dobrze => Mam wyjście. – ctamisier

+0

Następnie musi wyjść, zanim uruchomi się 'onSuccess'. –

Odpowiedz

21

Twój Oczekujcie czeka na przyszłość, aby zakończyć, który odbywa się po 2 sekundach, ale nie czekać na onSuccess obsługi, która wykonuje w innym wątku (podobny do przyszłości), ale po Await.ready(f, 60 seconds), więc proces wychodzi wcześniej, niż coś drukujesz. Aby przetworzyć go poprawnie - stworzyć nową przyszłość dla onComplete:

val f: Future[String] = Future { 
    Thread.sleep(2000) 
    "future value" 
} 

val f2 = f map { s => 
    println("OK!") 
    println("OK!")  
} 

Await.ready(f2, 60 seconds) 
println("exit") 

wyników dla Await.ready(f, ...):

exit 
OK! 
OK! 

wyników dla Await.ready(f2, ...):

OK! 
OK! 
exit 
+0

Ok, świetnie, zrozumiałem. Więc jeśli się nie mylę, jest to obejście, gdy używamy funkcji main(). Czy uważasz, że ExecutionContext jest w to zaangażowany, a "specjalny" może temu zapobiec? Spojrzałem na Futures zaimplementowane przez twitter i wygląda na to, że ich "Scheduler" obsługuje to (nie potrzebuję czekać .ready lub owijam przyszłość tym samym przypadkiem użycia), ale to już inna historia. Dzięki za pomoc ! – ctamisier

+0

To nie jest obejście problemu. Jest to poprawny sposób robienia takich rzeczy (jeśli masz tylko jeden wątek z Awaitem w swojej aplikacji) - szczególnie w stylu funkcjonalnym - ponieważ masz tylko jeden wynik w swojej aplikacji - powinieneś go zwrócić (i tak poczekać) 'IO', jeśli twoja aplikacja jest oparta na REPL (w innych przypadkach - użytkownik powinien zamknąć ją ręcznie z UI, więc nie ma potrzeby czekania). Inną opcją jest użycie ExecutionContext (i bazowego ThreadPool), który tworzy wątki z flagą 'isDaemon' false - patrz http://stackoverflow.com/questions/16612517/execution-context-without-daemon-threads-for-futures. – dk14

+0

Dlaczego "Await.ready (f, ...):' wypisz 'OK!'? Nie ma 'println (" OK! ")' W 'f'. Nie wiem, jak pogodzić "f" z takim oczekiwanym wyjściem. –

-8

Wystarczy umieścić readLine() w kodzie.