2015-01-26 12 views
13

Eseguendo questo codice scala, non ho alcun output nella console. (Non capisco cosa sta succedendo)Utilizzo di futures e Thread.sleep

Se rimuovo Console.println("Console.println OK!") => tutto sembra a posto.

Se rimuovo Thread.sleep(2000) => tutto sembra a posto.

Avete qualche idea al riguardo? Grazie mille!

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

Funziona bene per me. Cosa succede se si dorme per alcuni secondi dopo "Await.ready'? –

+0

Se dormo qualche secondo dopo 'Await.ready' funziona bene => Ho l'output. – ctamisier

+0

Quindi deve essere terminato prima che 'onSuccess' possa sparare. –

risposta

21

tuo await è in attesa di futuro per completare, che è fatto dopo 2 secondi, ma non aspetta onSuccess gestore, che esegue in un altro thread (simile al futuro), ma dopo Await.ready(f, 60 seconds), quindi il processo si chiude prima di aver stampato qualcosa. Per elaborare in modo corretto - creare un nuovo futuro per 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") 

Risultati per Await.ready(f, ...):

exit 
OK! 
OK! 

Risultati per Await.ready(f2, ...):

OK! 
OK! 
exit 
+0

Ok, ho capito bene. Quindi, se non sbaglio: questa è una soluzione alternativa quando usiamo una funzione main(). Pensi che l'ExecutionContext sia coinvolto in questo e uno "speciale" possa impedirlo? Ho dato un'occhiata ai Futures implementati da Twitter e sembra che il loro "Scheduler" gestisca questo (non ho bisogno di attendere.ready o avvolgere il futuro con lo stesso caso d'uso), ma questa è un'altra storia. Grazie per l'aiuto ! – ctamisier

+0

Non è una soluzione alternativa. È un modo corretto di fare queste cose (se hai un solo thread con Await nella tua applicazione) - specialmente per lo stile funzionale - dato che hai un solo risultato nella tua applicazione - dovresti restituirlo (e quindi aspettare) a 'IO' se la tua applicazione è basata su REPL (in altri casi - l'utente dovrebbe spegnerlo manualmente dall'interfaccia utente, quindi non c'è bisogno di attendere). Un'altra opzione - è usare ExecutionContext (e ThreadPool sottostante), che crea i thread con il flag 'isDaemon' false - vedi http://stackoverflow.com/questions/16612517/execution-context-without-daemon-threads-for-futures. – dk14

+0

Perchè 'Await.ready (f, ...):' stampa 'OK!'? Non c'è 'println (" OK! ")' In 'f'. Non so come riconciliare 'f' con un risultato atteso. –

-8

appena messo readLine() nel codice.